Skip to content

fix: preserve stored widget property metadata on ALTER PAGE REPLACE (CE0463) - #797

Open
ront85 wants to merge 1 commit into
mendixlabs:mainfrom
ront85:fix/112-replace-widget-ce0463
Open

fix: preserve stored widget property metadata on ALTER PAGE REPLACE (CE0463)#797
ront85 wants to merge 1 commit into
mendixlabs:mainfrom
ront85:fix/112-replace-widget-ce0463

Conversation

@ront85

@ront85 ront85 commented Jul 28, 2026

Copy link
Copy Markdown

Problem

Any ALTER PAGE … REPLACE of a pluggable widget produces CE0463 ("The definition of this widget has changed…") on the rebuilt widget — even an identity rebuild that changes nothing:

alter page DOC."SalesDocumentType_Select" {
  replace "comboBox1" with {
    combobox "comboBox1" (
      Attribute: "DOC.DocumentTypeSelector_Partner",
      DataSource: database from MasterData."Partner",
      CaptionAttribute: "Name"
    )
  }
}

mxcli reports success and mxcli check --references passes; only a real MxBuild check catches it. This blocks the whole class of "adjust an existing pluggable widget" edits (e.g. adding an XPath constraint to a combobox datasource). Reproduced identically on v0.13.0 and v0.16.0 against a Mendix 11.12.2 MPRv2 project with Combobox v2.8.1.

Root cause

The rebuild emits CustomWidgets$WidgetPropertyType metadata generated from the embedded template + installed .mpk, while untouched sibling widgets in the same page unit carry metadata from whichever (older) widget version authored them in Studio Pro. A byte-level diff of the page unit before/after an identity rebuild showed exactly two divergences, both per-property display metadata:

Property Stored by Studio Pro Emitted by mxcli
filterInputDebounceIntervalCategory Advanced::Filter Events
onChangeEventCaption On selection On change

A rebuilt widget and its neighbours end up described by two different widget versions in one file, and MxBuild rejects the mix.

Note on #112 (closed): its stated root cause — the template having more PropertyTypes than WidgetProperties — is not the defect. That asymmetry is intentional (system properties Label/Visibility/Editability deliberately have no value entry, per the comment in modelsdk/widgets/generate.go), and 13 other shipped templates share it while working fine. The actual defect is the metadata vintage mismatch above.

Fix

Mutator.ReplaceWidget now grafts the stored (old) widget's per-property display metadata — Caption, Category, Description — onto the replacement's freshly generated Type block, so the rebuilt widget stays consistent with the stored model rather than with the toolchain's template:

  • Matched by slash-joined PropertyKey path (/markers/latitude), not flat key, so distinct nested object types that reuse a key keep independent metadata.
  • Applied only when the replacement's WidgetId matches the replaced widget's — including pluggable widgets nested inside container replacements.
  • Leaf display fields only. $IDs and ValueTypes are never copied, so the replacement's ObjectType cross-references (freshly generated IDs) stay intact.
  • Properties the stored widget doesn't define (added in newer widget versions) keep their generated metadata.
  • No-ops safely when the replaced widget isn't a pluggable widget or the replacement is a different widget package.

This is deliberately scoped to REPLACE, where "match the stored model" is unambiguous; the wider template/schema question stays with #529.

Verification

  • 6 new unit tests in mdl/backend/pagemutator (same-widget graft, different-WidgetId untouched, non-pluggable old widget, nested object types, duplicate keys scoped by path, combobox nested in container replacement).
  • Full go test ./... passes; make lint-go clean.
  • End-to-end against a real Mendix 11.12.2 MPRv2 project (Combobox v2.8.1, Studio Pro–authored pages):
    • Before: identity rebuild → docker check → 1 error (CE0463).
    • After: identity rebuild → 0 errors; the stored Caption/Category values are preserved byte-for-byte in the unit.
    • After: REPLACE adding a where [Name != ''] XPath datasource constraint → 0 errors, constraint present in the unit.

…loses mendixlabs#112)

Replacing a pluggable widget emitted Type metadata (per-property
Caption/Category) generated from the embedded template and installed
.mpk, while untouched sibling widgets in the same page unit carried
metadata from whichever widget version authored them in Studio Pro.
MxBuild flags the mixed vintages as CE0463 on the rebuilt widget, even
for an identity rebuild that changes nothing.

ReplaceWidget now grafts the stored widget's per-property display
metadata (Caption, Category, Description) onto the replacement's
freshly generated Type block:

- matched by slash-joined PropertyKey path, not flat key, so distinct
  nested object types that reuse a key (e.g. markers/latitude vs
  dynamicMarkers/latitude) stay independent
- only onto replacements of the same WidgetId, including pluggable
  widgets nested inside container replacements
- leaf display fields only; $IDs and ValueTypes are never copied, so
  the new widget's Object/Type cross-references stay intact

Verified against a Mendix 11.12.2 MPRv2 project with Combobox v2.8.1:
identity rebuild and datasource-XPath replace both now pass docker
check with zero errors (previously CE0463 on both).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ront85

ront85 commented Jul 28, 2026

Copy link
Copy Markdown
Author

Update: I re-tested both repros in this PR against unpatched upstream/main (i.e. without this PR's change) and they now pass with 0 errors — including with --no-update-widgets, which rules out the docker pre-flight remediation as the explanation.

Root cause: #8a14fc2d ("reconcile ComboBox definition drift generically — close #112 CE0463", merged 2026-07-20) made the freshly-emitted CustomWidgetType byte-identical (ID-masked) to mx update-widgets output for the ComboBox drift case. That fix landed after v0.16.0 and after the environment (v0.13.0) I originally reproduced this on, and it appears to close the same underlying drift this PR targets, just via a different mechanism (fixing the .mpk parser's property ordering/assignableTo handling rather than grafting stored metadata during REPLACE).

I no longer have a reproducible failure on current main for the scenarios in this PR's description. I'm going to hold off on merging this until I can find a case 8a14fc2 doesn't cover (if one exists) — will update or close depending on what I find. Apologies for the noise; posting this rather than leaving a possibly-redundant PR silently open.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant