Skip to content

mxcli docker check silently converts MPRv2 projects to MPRv1 (via mx update-widgets), deleting mprcontents #763

Description

@dimenus

Summary

mxcli docker check silently converts an MPRv2 project to the self-contained MPRv1 storage
format. It inlines every unit into the .mpr (adds the Unit.Contents column) and deletes
the entire mprcontents/ directory. A command whose job is to check the project should not
rewrite the on-disk storage format.

The cause is the mx update-widgets step that mxcli docker check runs before mx check.
update-widgets performs the conversion; the check itself does not.

On a project under Git this is damaging: after the conversion the working tree no longer
matches the mprcontents/*.mxunit files tracked in the repository. If the project is then
opened in Studio Pro (which auto-converts back to MPRv2) or the state is committed, the
history and the on-disk format drift apart. In our case Studio Pro 11.12.1 then failed to
open the project at all, crashing in its Git version-control provider
(LibGit2RepositoryProvider.WriteBaseFile).

Environment

  • mxcli v0.16.0 (darwin-arm64, macOS 15.6.1)
  • mx from Studio Pro 11.12.1 Beta (the bundled binary that mxcli docker check resolves
    on macOS)
  • Project version 11.12.1, MPRv2 storage format (mprcontents/ present)

Reproduction

Format oracle used throughout (1 = MPRv1 self-contained, 0 = MPRv2):

sqlite3 App.mpr "SELECT COUNT(*) FROM pragma_table_info('Unit') WHERE name='Contents';"

Starting from a clean MPRv2 project (oracle returns 0, mprcontents/ populated), each step
run against an isolated copy:

  1. Model writes via mxcli exec (alter page, create-or-replace page) → still v2. mxcli's
    own writer preserves the storage format.
  2. Plain mx check App.mpr (bundled binary, called directly) → still v2. The check is
    read-only.
  3. mx update-widgets App.mprv1. The oracle returns 1 and mprcontents/ is deleted.

mxcli docker check runs step 3 (as its "Updating widget definitions..." phase) before the
check, so the whole command reverts v2 → v1:

mxcli docker check -p App.mpr
# Updating widget definitions in App.mpr...
# Widget definitions updated.
# Checking project App.mpr...
# ...
# The app contains: 0 errors.

sqlite3 App.mpr "SELECT COUNT(*) FROM pragma_table_info('Unit') WHERE name='Contents';"
# 1   <- now MPRv1; mprcontents/ is gone

Impact

  • Silent storage-format change from a command named check.
  • On a Git project, HEAD and the working tree diverge, which can corrupt the repository
    state and (observed here) make Studio Pro unable to open the project.
  • The conversion is easy to miss: the check reports 0 errors and looks successful.

Suggestions

  • mxcli docker check should not leave the project in a different storage format than it
    found it. Either skip update-widgets, run it against a temporary copy, or convert back to
    MPRv2 afterwards.
  • At minimum, warn loudly when a check (or update-widgets) is about to rewrite the storage
    format, and skip it when the project is MPRv2.
  • Independently, mx update-widgets converting v2 → v1 looks like a platform-side surprise
    worth raising with Mendix; but mxcli can shield users from it in the docker check flow.

Workaround

Validate with the bundled mx check directly instead of mxcli docker check:

"/Applications/Mendix Studio Pro <ver>*.app/Contents/modeler/mx" check /abs/path/App.mpr

The trade-off is that skipping update-widgets can surface CE0463 widget-definition-drift
false positives, which then need to be judged by hand. If a project has already been
reverted, reopening it in Studio Pro converts it back to MPRv2 and regenerates
mprcontents/.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions