Skip to content

CE0463 on every mxcli-authored Barcode Scanner: an object list the author never wrote is seeded with a placeholder row #1161

Description

@MendixMau

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.

Note on #891

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions