Summary
A page authored by mxcli that contains a Barcode Scanner widget cannot be deployed: mxbuild rejects it with CE0463 — "The definition of this widget has changed. Update this widget by right-clicking it and selecting 'Update widget'".
mxcli check --references and mx check both report zero errors on the same model. The failure only appears at mxbuild / app-run time, so nothing in the mxcli workflow catches it.
The same class of bug also affects the HTML element widget's events property.
Environment
|
|
| mxcli |
v0.23.0 (2026-09-21T11:10:32Z) — stock release binary |
| Mendix |
11.14.0 (mxbuild 11.14.0) |
| Widget |
Barcode Scanner (com.mendix.widget.web.BarcodeScanner.mpk) 2.5.0 |
| OS / Go |
macOS 26.6.2 arm64 / go1.26.4 |
Expected behaviour
mxcli exec writes a Barcode Scanner whose stored instance matches the installed .mpk, and the app builds.
Actual behaviour
mxbuild fails. One CE0463 per Barcode Scanner on the page.
Minimal reproduction
repro.mdl — four statements, no dependency on anything in the host app:
create module "ReproScan";
/
create entity "ReproScan"."Ticket" (
"Code" : string(200)
);
/
create or replace microflow "ReproScan"."DS_Ticket" ()
returns "ReproScan"."Ticket"
begin
$New = create "ReproScan"."Ticket" ("Code" = '');
return $New;
end;
/
create or replace page "ReproScan"."ScanPage" (
Title: 'Scan',
Layout: "Atlas_Core"."Atlas_Default"
) {
dataview "dv" (DataSource: microflow "ReproScan"."DS_Ticket") {
barcodescanner "bsCode" (datasource: "Code")
}
}
/
Run against any app that has Barcode Scanner 2.5.0 in widgets/:
$ mxcli check repro.mdl -p App.mpr --references
Checking syntax: repro.mdl
✓ Syntax OK (4 statements)
Validating references against: App.mpr
Connected to: App.mpr (Mendix 11.14.0)
✓ All references valid
$ mxcli exec repro.mdl -p App.mpr
Connected to: App.mpr (Mendix 11.14.0)
Created module: ReproScan
Created entity: ReproScan.Ticket
Created microflow: ReproScan.DS_Ticket
Created page ReproScan.ScanPage
$ ~/.mxcli/mxbuild/11.14.0/modeler/mxbuild App.mpr ; echo "exit=$?"
ERROR: The project cannot be deployed, because it contains errors.
ERROR at ReproScan, Page 'ScanPage', Barcode Scanner 'bsCode': The definition of
this widget has changed. Update this widget by right-clicking it and selecting
'Update widget', or select 'Update all widgets' to update all widgets in the app.
BUILD FAILED
exit=3
Opening the app in Studio Pro and choosing Update widget on bsCode makes it build — and the only thing Studio Pro changes is deleting a row from the barcodeFormats object list.
Root cause
Builder.EnsureRequiredObjectLists (mdl/backend/widgetobj/builder.go) seeds one placeholder row into any object-list property whose nested properties are all "simple" — the skip list is Attribute / Expression / TextTemplate / Widgets / DataSource.
barcodeFormats is declared in the widget XML with no required attribute at all:
<property key="barcodeFormats" type="object" isList="true">
<properties><propertyGroup caption="Object list group">
<property key="barcodeFormat" type="enumeration" defaultValue="AZTEC">
The mpk reader defaults an absent attribute to required — mdl/.../mpk.go: Required: p.Required != "false" — so the property arrives marked required, and its single nested member is an Enumeration, which is not in the skip list. mxcli therefore seeds a row carrying the enum default AZTEC. Studio Pro writes the list empty, so the stored instance disagrees with the .mpk and mxbuild raises CE0463.
BSON oracle. Diffing mxcli bson dump --object ReproScan.ScanPage from a stock-authored model against one authored without the seeding, ignoring the regenerated $ID/TypePointer blobs, yields exactly one hunk:
> { "Key": "$Type", "Value": "CustomWidgets$WidgetObject" }, <- the seeded row
> ...
> { "Key": "PrimitiveValue", "Value": "AZTEC" }
4 CustomWidgets$WidgetObject nodes vs 3. Nothing else in the page differs.
Blast radius
Scanning the 31 shipped widget templates, this heuristic fires on exactly two properties, and Studio Pro leaves both empty:
| widget |
property |
declared |
nested types |
barcodescanner |
barcodeFormats |
required (by absent attribute) |
{Enumeration} |
htmlelement |
events |
optional |
{Action, Boolean, Enumeration} |
Zero beneficiaries, two victims.
This is not the same rule as #891. That fix fills an authored object-list item's required TextTemplate with the widget's shipped translations; it lives in buildObjectListItemBSON and is unaffected. The inference "absent required attribute means required" is also correct and stays. The defect is specifically materialising a row the author never wrote.
Not a duplicate
Both are distinct code paths from object-list seeding.
Open question / limits of the evidence
The two-property surface above is measured against the shipped widget templates only. A third-party widget with a required object list whose nested properties are all simple would also stop being seeded — which is the correct behaviour (Studio Pro would leave it empty too), but I cannot prove no user relies on the old behaviour.
Proposed fix
Remove the seeding: make EnsureRequiredObjectLists a no-op and drop ensureRequiredObjectLists / createDefaultWidgetObject. The MCP write path (mdl/backend/mcp/widget.go) already implements this method as a no-op, so removal also makes the two engines agree instead of leaving the model dependent on which one authored it.
I have a branch ready with the fix, a CHANGELOG entry, and a regression test that fails on both subtests against current main — happy to open the PR if you'd like it. Per CONTRIBUTING I'm filing this first and waiting for approval.
Summary
A page authored by mxcli that contains a Barcode Scanner widget cannot be deployed:
mxbuildrejects it with CE0463 — "The definition of this widget has changed. Update this widget by right-clicking it and selecting 'Update widget'".mxcli check --referencesandmx checkboth report zero errors on the same model. The failure only appears atmxbuild/ app-run time, so nothing in the mxcli workflow catches it.The same class of bug also affects the HTML element widget's
eventsproperty.Environment
v0.23.0 (2026-09-21T11:10:32Z)— stock release binarymxbuild11.14.0)com.mendix.widget.web.BarcodeScanner.mpk) 2.5.0Expected behaviour
mxcli execwrites a Barcode Scanner whose stored instance matches the installed.mpk, and the app builds.Actual behaviour
mxbuildfails. One CE0463 per Barcode Scanner on the page.Minimal reproduction
repro.mdl— four statements, no dependency on anything in the host app:Run against any app that has Barcode Scanner 2.5.0 in
widgets/:Opening the app in Studio Pro and choosing Update widget on
bsCodemakes it build — and the only thing Studio Pro changes is deleting a row from thebarcodeFormatsobject list.Root cause
Builder.EnsureRequiredObjectLists(mdl/backend/widgetobj/builder.go) seeds one placeholder row into any object-list property whose nested properties are all "simple" — the skip list isAttribute / Expression / TextTemplate / Widgets / DataSource.barcodeFormatsis declared in the widget XML with norequiredattribute at all:The mpk reader defaults an absent attribute to required —
mdl/.../mpk.go:Required: p.Required != "false"— so the property arrives marked required, and its single nested member is an Enumeration, which is not in the skip list. mxcli therefore seeds a row carrying the enum defaultAZTEC. Studio Pro writes the list empty, so the stored instance disagrees with the.mpkand mxbuild raises CE0463.BSON oracle. Diffing
mxcli bson dump --object ReproScan.ScanPagefrom a stock-authored model against one authored without the seeding, ignoring the regenerated$ID/TypePointerblobs, yields exactly one hunk:4
CustomWidgets$WidgetObjectnodes vs 3. Nothing else in the page differs.Blast radius
Scanning the 31 shipped widget templates, this heuristic fires on exactly two properties, and Studio Pro leaves both empty:
barcodescannerbarcodeFormats{Enumeration}htmlelementevents{Action, Boolean, Enumeration}Zero beneficiaries, two victims.
Note on #891
This is not the same rule as #891. That fix fills an authored object-list item's required
TextTemplatewith the widget's shipped translations; it lives inbuildObjectListItemBSONand is unaffected. The inference "absentrequiredattribute means required" is also correct and stays. The defect is specifically materialising a row the author never wrote.Not a duplicate
pagingPositionenum-key handling.Both are distinct code paths from object-list seeding.
Open question / limits of the evidence
The two-property surface above is measured against the shipped widget templates only. A third-party widget with a required object list whose nested properties are all simple would also stop being seeded — which is the correct behaviour (Studio Pro would leave it empty too), but I cannot prove no user relies on the old behaviour.
Proposed fix
Remove the seeding: make
EnsureRequiredObjectListsa no-op and dropensureRequiredObjectLists/createDefaultWidgetObject. The MCP write path (mdl/backend/mcp/widget.go) already implements this method as a no-op, so removal also makes the two engines agree instead of leaving the model dependent on which one authored it.I have a branch ready with the fix, a CHANGELOG entry, and a regression test that fails on both subtests against current
main— happy to open the PR if you'd like it. Per CONTRIBUTING I'm filing this first and waiting for approval.