mxcli bug: ALTER PAGE corrupts DataGrid2 ShowContentAs: customContent columns
mxcli version
nightly-20260720-88077af1 (2026-07-20T06:06:00Z)
Mendix version
10.24.20.105674
Severity
High. mxcli check (syntax + --references) and the ALTER PAGE command itself report success with no warning, but the resulting .mpr crashes mx check / mxcli docker check on load with an unhandled .NET exception (project becomes completely unloadable/unbuildable, not just the one page). A second, related symptom silently truncates/corrupts existing widget bindings (data loss in the model) with no error at all. Both are silent — nothing in mxcli's own output flags either problem; only a subsequent mx check/docker check run reveals it.
Summary
Two related defects, both triggered by ALTER PAGE (insert or replace) touching a DataGrid2 column that has ShowContentAs: customContent:
- Crash: any column inserted or rewritten via
ALTER PAGE with ShowContentAs: customContent whose content is a plain container produces a BSON structure that mxcli describe reads back fine, but that the real Mendix loader (mx check, used internally by mxcli docker check) cannot deserialize — InvalidCastException: DivContainer -> WidgetObject. This also reproduces when re-writing (via insert/replace) columns that were originally authored in Studio Pro and worked fine before the ALTER PAGE touched them — i.e. ALTER PAGE can retroactively break pre-existing, previously-valid columns it rewrites as a side effect, not just newly-added ones.
- Silent ContentParams truncation: independently of the crash, when a
ShowContentAs: customContent column's nested DYNAMICTEXT has a ContentParams expression referencing an association path with 2+ hops (e.g. AssocA/AssocB/Attr), writing that column via ALTER PAGE (insert or replace) silently truncates/mangles the expression — e.g. AssocA/AssocB/Attr round-trips as garbage-tokenized text, or as <unbound> (i.e. the attribute reference becomes null). No error or warning is produced; the corruption is only visible via a subsequent describe page or a full mx check.
Note: per create-page.md's own note, CREATE PAGE with ShowContentAs: customContent is documented as "mxbuild-verified, 0 errors" — the defect appears specific to the ALTER PAGE write path (insert/replace), not page creation from scratch.
Steps to reproduce (project-independent)
Minimal domain model:
create persistent entity Sample.Customer (
Name: string(100)
);
/
create persistent entity Sample.Order (
Number: string(50)
);
/
create association Sample.Order_Customer
from Sample.Order to Sample.Customer
type reference;
/
A page with a DataGrid2 that has at least one pre-existing customContent column bound to a 2-hop association path (this mirrors a Studio-Pro-authored page — create it with CREATE PAGE, which works fine and is mxbuild-clean):
create page Sample.Order_Overview (
title: 'Orders',
layout: Atlas_Core.Atlas_Default
) {
datagrid dataGrid1 (datasource: database from Sample.Order) {
column "Order_Customer/Name" (
attribute: Order_Customer/Name,
caption: 'Customer',
ShowContentAs: customContent
) {
container ctnName (designproperties: ['Spacing': ['margin-left': 'S']]) {
dynamictext txtName (
content: '{1}',
contentparams: [{1} = Sample.Order_Customer/Sample.Customer/Name]
)
}
}
}
}
/
Verify this page is clean: mxcli docker check -p sample.mpr → 0 errors.
Repro 1 (crash): insert a second customContent column via ALTER PAGE:
alter page Sample.Order_Overview {
insert after dataGrid1.Name {
column colFlag (caption: ' ', ShowContentAs: customContent) {
container ctnFlag (visible: [$currentObject/Order_Customer/Name != '']) {
dynamictext txtFlag (content: '!')
}
}
}
};
mxcli check/exec report success (Altered page Sample.Order_Overview). Then run:
mxcli docker check -p sample.mpr
→ crashes with System.InvalidCastException: Unable to cast object of type '...DivContainer' to type '...WidgetObject' during Loading the mpr file (before any per-page validation is even printed).
Repro 2 (silent truncation): instead of inserting, replace the pre-existing 2-hop column (or the whole datagrid dataGrid1 widget) with an MDL block containing the identical original text (byte-for-byte, copied from describe page):
alter page Sample.Order_Overview {
replace "Order_Customer/Name" with {
column "Order_Customer/Name" (
attribute: Order_Customer/Name,
caption: 'Customer',
ShowContentAs: customContent
) {
container ctnName (designproperties: ['Spacing': ['margin-left': 'S']]) {
dynamictext txtName (
content: '{1}',
contentparams: [{1} = Sample.Order_Customer/Sample.Customer/Name]
)
}
}
}
};
mxcli exec reports success with no error. Then describe page Sample.Order_Overview shows the contentparams value corrupted (truncated tokens, e.g. dropping the leading Sample.Order_Customer/Sample. prefix and leaving a dangling fragment) or shown as <unbound>, and mxcli docker check then fails to load the project (InvalidOperationException/ArgumentNullException setting AttributeRef.AttributeId, i.e. the reference is now null).
Expected behaviour
ALTER PAGE insert/replace on a customContent DataGrid2 column should produce a .mpr that loads and builds cleanly in mx check, identical in effect to the same structure authored via Studio Pro or via CREATE PAGE. Multi-hop ContentParams association expressions should round-trip unchanged.
Actual behaviour (verbatim from my session)
- After an
ALTER PAGE insert adding 3 new customContent columns (each a container + dynamictext) to a pre-existing DataGrid2, mxcli check/exec reported success. mxcli docker check -p project/MIC.mpr then failed while still printing Loading the mpr file (i.e. before reaching any page-specific check), with:
ERROR: System.InvalidCastException: Unable to cast object of type 'Mendix.Modeler.WebUI.Forms.Widgets.LayoutWidgets.DivContainers.DivContainer' to type 'Mendix.Modeler.WebUI.Forms.Widgets.CustomWidgets.WidgetObject'.
at Mendix.Modeler.Utility.Collections.DefaultList`1.System.Collections.IList.Add(Object value) in Mendix.Modeler.Utility\Collections\List\DefaultList.cs:line 94
at Mendix.Modeler.Storage.Operations.UnitContentsLoader.FillProperties(...)
at Mendix.Modeler.Storage.Operations.UnitContentsLoader.ConstructObjectInternal(...)
... (repeats through nested FillProperties/ConstructObjectInternal/ConvertFromStorage frames) ...
at Mendix.MxToolset.Check.CheckRunner.LoadProject(CheckOptions options)
- Dropping the 3 newly-added columns (
drop widget dataGrid<n>.col2, dataGrid<n>.col3, dataGrid<n>.col4) did not clear the crash — the identical InvalidCastException persisted, because a later ALTER PAGE replace <datagrid> with {...} (attempting to rewrite the whole grid, including its original, previously-untouched columns, back to their documented text) re-triggered the same cast failure on those original columns too. Only fully drop widget-ing the entire DataGrid2 (no re-insert) restored a loadable project.
- Separately, after a
replace of a single pre-existing column whose dynamictext had ContentParams: [{1} = Module.Association1/Module.Association2/Attr] (an exact copy of what describe page had shown for that same widget, previously valid), the next describe page showed the value corrupted to a short, garbled fragment (e.g. the leading Module.Association1/Module. segment dropped, leaving a dangling, unparseable tail concatenated with unrelated text from an adjacent expression), and a different column's equivalent single-hop reference came back as contentparams: [{1} = <unbound>]. mxcli docker check on that state failed during Loading the mpr file with:
ERROR: System.InvalidOperationException: An error occurred when trying to set the 'Attribute' property of a Attribute in a Page with ID <page-guid>.
---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.ArgumentNullException: Value cannot be null. (Parameter 'value')
at Mendix.Modeler.DomainModels.Refs.AttributeRef.set_AttributeId(AttributeIdentifier value)
- Both symptoms reproduced identically whether the triggering
ALTER PAGE used insert or replace, and whether the ContentParams expression was written single-line or multi-line.
Workaround
None that preserves the feature. What I did to restore a loadable project: alter page Module.Page { drop widget <dataGridName> } — removed the entire DataGrid2 (not just the newly-added columns) rather than attempt further insert/replace repairs, since each repair attempt reproduced one of the two symptoms above. The page is left without its results table; restoring it requires manually re-adding the DataGrid2 in Studio Pro. Columns that do not use ShowContentAs: customContent (plain attribute-bound columns) were not observed to be affected — only customContent columns.
Diagnostic bundle
Available: yes — mxcli-diag-20260819-220247.tar.gz (workspace root). Note: the bundle's log only contains abstract execute_error lines for the failed ALTER PAGE attempts, without the full InvalidCastException/ArgumentNullException stack traces quoted above — those were captured directly from the mxcli docker check terminal output during the session and are not otherwise present in the bundle.
mxcli bug: ALTER PAGE corrupts DataGrid2
ShowContentAs: customContentcolumnsmxcli version
nightly-20260720-88077af1 (2026-07-20T06:06:00Z)Mendix version
10.24.20.105674Severity
High.
mxcli check(syntax +--references) and theALTER PAGEcommand itself report success with no warning, but the resulting.mprcrashesmx check/mxcli docker checkon load with an unhandled .NET exception (project becomes completely unloadable/unbuildable, not just the one page). A second, related symptom silently truncates/corrupts existing widget bindings (data loss in the model) with no error at all. Both are silent — nothing inmxcli's own output flags either problem; only a subsequentmx check/docker checkrun reveals it.Summary
Two related defects, both triggered by
ALTER PAGE(insertorreplace) touching a DataGrid2 column that hasShowContentAs: customContent:ALTER PAGEwithShowContentAs: customContentwhose content is a plaincontainerproduces a BSON structure thatmxcli describereads back fine, but that the real Mendix loader (mx check, used internally bymxcli docker check) cannot deserialize —InvalidCastException: DivContainer -> WidgetObject. This also reproduces when re-writing (viainsert/replace) columns that were originally authored in Studio Pro and worked fine before theALTER PAGEtouched them — i.e.ALTER PAGEcan retroactively break pre-existing, previously-valid columns it rewrites as a side effect, not just newly-added ones.ShowContentAs: customContentcolumn's nestedDYNAMICTEXThas aContentParamsexpression referencing an association path with 2+ hops (e.g.AssocA/AssocB/Attr), writing that column viaALTER PAGE(insertorreplace) silently truncates/mangles the expression — e.g.AssocA/AssocB/Attrround-trips as garbage-tokenized text, or as<unbound>(i.e. the attribute reference becomes null). No error or warning is produced; the corruption is only visible via a subsequentdescribe pageor a fullmx check.Note: per
create-page.md's own note,CREATE PAGEwithShowContentAs: customContentis documented as "mxbuild-verified, 0 errors" — the defect appears specific to theALTER PAGEwrite path (insert/replace), not page creation from scratch.Steps to reproduce (project-independent)
Minimal domain model:
A page with a DataGrid2 that has at least one pre-existing
customContentcolumn bound to a 2-hop association path (this mirrors a Studio-Pro-authored page — create it withCREATE PAGE, which works fine and is mxbuild-clean):Verify this page is clean:
mxcli docker check -p sample.mpr→ 0 errors.Repro 1 (crash): insert a second
customContentcolumn viaALTER PAGE:mxcli check/execreport success (Altered page Sample.Order_Overview). Then run:→ crashes with
System.InvalidCastException: Unable to cast object of type '...DivContainer' to type '...WidgetObject'duringLoading the mpr file(before any per-page validation is even printed).Repro 2 (silent truncation): instead of inserting,
replacethe pre-existing 2-hop column (or the wholedatagrid dataGrid1widget) with an MDL block containing the identical original text (byte-for-byte, copied fromdescribe page):mxcli execreports success with no error. Thendescribe page Sample.Order_Overviewshows thecontentparamsvalue corrupted (truncated tokens, e.g. dropping the leadingSample.Order_Customer/Sample.prefix and leaving a dangling fragment) or shown as<unbound>, andmxcli docker checkthen fails to load the project (InvalidOperationException/ArgumentNullExceptionsettingAttributeRef.AttributeId, i.e. the reference is now null).Expected behaviour
ALTER PAGE insert/replaceon acustomContentDataGrid2 column should produce a.mprthat loads and builds cleanly inmx check, identical in effect to the same structure authored via Studio Pro or viaCREATE PAGE. Multi-hopContentParamsassociation expressions should round-trip unchanged.Actual behaviour (verbatim from my session)
ALTER PAGE insertadding 3 newcustomContentcolumns (each acontainer+dynamictext) to a pre-existing DataGrid2,mxcli check/execreported success.mxcli docker check -p project/MIC.mprthen failed while still printingLoading the mpr file(i.e. before reaching any page-specific check), with:drop widget dataGrid<n>.col2, dataGrid<n>.col3, dataGrid<n>.col4) did not clear the crash — the identicalInvalidCastExceptionpersisted, because a laterALTER PAGE replace <datagrid> with {...}(attempting to rewrite the whole grid, including its original, previously-untouched columns, back to their documented text) re-triggered the same cast failure on those original columns too. Only fullydrop widget-ing the entire DataGrid2 (no re-insert) restored a loadable project.replaceof a single pre-existing column whosedynamictexthadContentParams: [{1} = Module.Association1/Module.Association2/Attr](an exact copy of whatdescribe pagehad shown for that same widget, previously valid), the nextdescribe pageshowed the value corrupted to a short, garbled fragment (e.g. the leadingModule.Association1/Module.segment dropped, leaving a dangling, unparseable tail concatenated with unrelated text from an adjacent expression), and a different column's equivalent single-hop reference came back ascontentparams: [{1} = <unbound>].mxcli docker checkon that state failed duringLoading the mpr filewith:ALTER PAGEusedinsertorreplace, and whether the ContentParams expression was written single-line or multi-line.Workaround
None that preserves the feature. What I did to restore a loadable project:
alter page Module.Page { drop widget <dataGridName> }— removed the entire DataGrid2 (not just the newly-added columns) rather than attempt furtherinsert/replacerepairs, since each repair attempt reproduced one of the two symptoms above. The page is left without its results table; restoring it requires manually re-adding the DataGrid2 in Studio Pro. Columns that do not useShowContentAs: customContent(plain attribute-bound columns) were not observed to be affected — onlycustomContentcolumns.Diagnostic bundle
Available: yes —
mxcli-diag-20260819-220247.tar.gz(workspace root). Note: the bundle's log only contains abstractexecute_errorlines for the failedALTER PAGEattempts, without the fullInvalidCastException/ArgumentNullExceptionstack traces quoted above — those were captured directly from themxcli docker checkterminal output during the session and are not otherwise present in the bundle.