mxcli version
mxcli version v0.18.0 (2026-08-14T20:29:13Z)
Mendix version
10.24.24.119653
Severity
High.
Not a cosmetic rendering gap. Three independent read commands report a page as
containing nothing that it demonstrably does contain, with no warning, no
NEEDS VERIFICATION marker, and no non-zero exit code. Concretely:
SHOW REFERENCES TO <entity> under-reports. An entity used by a Data Grid 2
inside a specialization template reports 0 pages, 0 widgets. Any tooling or
agent that uses reference counts to decide "unused, safe to delete" will delete a
document that is in active use.
DESCRIBE PAGE output is presented as complete and is not. It renders one
template's body inline as if it were the list view body, and drops the sibling
template entirely — so the output is not merely incomplete, it is misleading about
the page's structure.
SEARCH misses it even with REFRESH CATALOG SOURCE. So there is no read
command that can find this content.
The data-loss vector is indirect but real: DESCRIBE PAGE emits
create or modify page, which the docs and common practice treat as a round-trippable
representation. Re-executing that output would write back a page without the omitted
template. On Mendix 10 this is blocked by an unrelated guard (see "Round-trip test"),
so we could not confirm the loss end-to-end — but nothing in the omission itself is
version-specific.
Steps to reproduce
There is no pure-CLI reproduction, and that is part of the report:
mxcli syntax page widgets shows the only List View form as
LISTVIEW name (DataSource: DATABASE Module.Entity) { ... }
a single body. MDL has no surface for per-specialization templates, so the page must
be built in Studio Pro.
Setup (Studio Pro):
- Domain model in
MyModule: a generalization BaseItem, with two specializations
TypeA and TypeB. A second entity ChildRecord with an association
ChildRecord_TypeB to TypeB.
- Page
MyModule.Parent_Edit. Put a List View on it over BaseItem.
- On that List View, add two templates (List View → Templates): one for
TypeA, one for TypeB.
- In the
TypeA template, put a few text boxes.
- In the
TypeB template, put a Data Grid 2 with DataSource: association ChildRecord_TypeB, two columns over ChildRecord attributes, and an action button
calling a microflow MyModule.ACT_TypeB_DoThing.
- Save and commit.
Then, with mxcli:
# 1. the TypeB template is absent from the output
mxcli -p MyApp.mpr -c "DESCRIBE PAGE MyModule.Parent_Edit"
# 2. reports 0 pages / 0 widgets
mxcli -p MyApp.mpr -c "SHOW REFERENCES TO MyModule.ChildRecord"
# 3. reports only the microflow itself, not Parent_Edit
mxcli -p MyApp.mpr -c "REFRESH CATALOG SOURCE"
mxcli -p MyApp.mpr -c "SEARCH 'ACT_TypeB_DoThing'"
# 4. ground truth: the content is in the model
mxcli bson dump -p MyApp.mpr --type page --object MyModule.Parent_Edit > page.json
grep -c '"Value": "Forms\$ListViewTemplate"' page.json # -> 2
grep -c 'MyModule.ChildRecord' page.json # -> non-zero
Expected behaviour
Either of these would be acceptable; the third would be ideal:
DESCRIBE PAGE renders every List View template, with its Entity, in a template
block — the way it already does for Gallery (template template1 { ... }).
- Or, if there is no MDL surface to render them into,
DESCRIBE PAGE emits an
explicit warning naming what was omitted (e.g.
-- WARNING: 1 list view template (MyModule.TypeB) omitted: no MDL representation),
so the output is never silently partial.
SHOW REFERENCES and SEARCH index widget contents inside specialization
templates regardless of whether DESCRIBE can render them. The indexer and the
serializer should not share this blind spot.
Actual behaviour
Measured on one real page holding exactly one List View with two templates
(Forms$ListView: 1, Forms$ListViewTemplate: 2):
| Command |
Reported |
Model truth |
DESCRIBE PAGE |
no template blocks at all; 353 lines; zero mentions of the specialization or its child entity |
2 templates; 19 references to the specialization's namespace |
SHOW REFERENCES TO <child entity> |
17 refs — 0 pages, 0 widgets |
1 page |
SHOW REFERENCES TO <the association> |
3 refs, all microflows |
+ 1 page |
SEARCH '<microflow>' (with REFRESH CATALOG SOURCE) |
2 documents: the microflow, and one unrelated page |
+ Parent_Edit |
DESCRIBE PAGE renders the first template's widgets inline directly under
listview listView1 (...) { ... }, with no template wrapper, which reads as "this list
view has one plain body". The second template is absent.
Round-trip test (what we verified about write safety)
We copied the project to an isolated directory and ran each ALTER PAGE operation
against it, re-dumping the page after each and counting the templates. All four
operations are safe — ALTER PAGE patches surgically and does not disturb the
templates it cannot see:
| Test |
Operation |
ListViewTemplate after |
Verdict |
| baseline |
— |
2 |
— |
| A |
SET Title = '...' (page-level) |
2 |
safe (+3 bytes = the 3 added title chars) |
| B |
INSERT AFTER <widget> inside the list view |
2 |
safe |
| C |
full round-trip: DESCRIBE PAGE output re-executed |
2 |
not executed — refused, see below |
| D |
REPLACE <widget> WITH { ... } inside the list view |
2 |
safe |
| E |
DROP WIDGET <widget> inside the list view |
2 |
safe |
Test C could not complete, for two separate reasons — both worth noting:
$ mxcli check testC.mdl -p MyApp.mpr --references
statement 1: page '...' has reference errors:
- entity not found: from
✗ 1 reference error(s) found
$ mxcli exec testC.mdl -p MyApp.mpr
Error: create page with parameters requires Mendix 11.0.0+ (project is 10.24.24.119653)
So on Mendix 10 the destructive path is blocked by the page-parameter guard, and
before that by the invalid MDL described in the next section. On Mendix 11+, where
the parameter guard does not apply, we would expect the round-trip to write back a
page with the template missing — we did not verify that, and it should be
confirmed before the severity here is finalised.
Related defect, filed separately
The entity not found: from error in test C above is a second, independent bug:
DESCRIBE PAGE emits database from for datasources that are not a database-over-entity
— sometimes with the entity slot blank, sometimes with a microflow name in it. It is
reported separately — see #941. It matters
here only because it blocks test C before the page-parameter guard does.
Workaround
Read the stored model directly, which is read-only and goes through mxcli:
mxcli bson dump -p MyApp.mpr --type page --object MyModule.Parent_Edit > page.json
grep -c '"Value": "Forms\$ListViewTemplate"' page.json
grep -n -i '<entity-or-microflow-name>' page.json
For write safety, prefer ALTER PAGE with targeted SET / INSERT / REPLACE /
DROP operations (verified safe above) and never re-execute DESCRIBE PAGE output
for a page whose List View has multiple templates.
Diagnostic bundle
Yes — mxcli-diag-20260820-132332.tar.gz, available on request. Not attached, because
it contains client model data.
Note on anonymisation
The entity, page, module and microflow names in this report are placeholders. The
defect was found on a private client project; the shapes, counts and command output
above are faithful to the real measurement, only the identifiers are renamed.
mxcli version
Mendix version
10.24.24.119653Severity
High.
Not a cosmetic rendering gap. Three independent read commands report a page as
containing nothing that it demonstrably does contain, with no warning, no
NEEDS VERIFICATIONmarker, and no non-zero exit code. Concretely:SHOW REFERENCES TO <entity>under-reports. An entity used by a Data Grid 2inside a specialization template reports 0 pages, 0 widgets. Any tooling or
agent that uses reference counts to decide "unused, safe to delete" will delete a
document that is in active use.
DESCRIBE PAGEoutput is presented as complete and is not. It renders onetemplate's body inline as if it were the list view body, and drops the sibling
template entirely — so the output is not merely incomplete, it is misleading about
the page's structure.
SEARCHmisses it even withREFRESH CATALOG SOURCE. So there is no readcommand that can find this content.
The data-loss vector is indirect but real:
DESCRIBE PAGEemitscreate or modify page, which the docs and common practice treat as a round-trippablerepresentation. Re-executing that output would write back a page without the omitted
template. On Mendix 10 this is blocked by an unrelated guard (see "Round-trip test"),
so we could not confirm the loss end-to-end — but nothing in the omission itself is
version-specific.
Steps to reproduce
There is no pure-CLI reproduction, and that is part of the report:
mxcli syntax page widgetsshows the only List View form asa single body. MDL has no surface for per-specialization templates, so the page must
be built in Studio Pro.
Setup (Studio Pro):
MyModule: a generalizationBaseItem, with two specializationsTypeAandTypeB. A second entityChildRecordwith an associationChildRecord_TypeBtoTypeB.MyModule.Parent_Edit. Put a List View on it overBaseItem.TypeA, one forTypeB.TypeAtemplate, put a few text boxes.TypeBtemplate, put a Data Grid 2 withDataSource: association ChildRecord_TypeB, two columns overChildRecordattributes, and an action buttoncalling a microflow
MyModule.ACT_TypeB_DoThing.Then, with mxcli:
Expected behaviour
Either of these would be acceptable; the third would be ideal:
DESCRIBE PAGErenders every List View template, with itsEntity, in atemplateblock — the way it already does for Gallery (
template template1 { ... }).DESCRIBE PAGEemits anexplicit warning naming what was omitted (e.g.
-- WARNING: 1 list view template (MyModule.TypeB) omitted: no MDL representation),so the output is never silently partial.
SHOW REFERENCESandSEARCHindex widget contents inside specializationtemplates regardless of whether
DESCRIBEcan render them. The indexer and theserializer should not share this blind spot.
Actual behaviour
Measured on one real page holding exactly one List View with two templates
(
Forms$ListView: 1,Forms$ListViewTemplate: 2):DESCRIBE PAGEtemplateblocks at all; 353 lines; zero mentions of the specialization or its child entitySHOW REFERENCES TO <child entity>SHOW REFERENCES TO <the association>SEARCH '<microflow>'(withREFRESH CATALOG SOURCE)Parent_EditDESCRIBE PAGErenders the first template's widgets inline directly underlistview listView1 (...) { ... }, with no template wrapper, which reads as "this listview has one plain body". The second template is absent.
Round-trip test (what we verified about write safety)
We copied the project to an isolated directory and ran each
ALTER PAGEoperationagainst it, re-dumping the page after each and counting the templates. All four
operations are safe —
ALTER PAGEpatches surgically and does not disturb thetemplates it cannot see:
ListViewTemplateafterSET Title = '...'(page-level)INSERT AFTER <widget>inside the list viewDESCRIBE PAGEoutput re-executedREPLACE <widget> WITH { ... }inside the list viewDROP WIDGET <widget>inside the list viewTest C could not complete, for two separate reasons — both worth noting:
So on Mendix 10 the destructive path is blocked by the page-parameter guard, and
before that by the invalid MDL described in the next section. On Mendix 11+, where
the parameter guard does not apply, we would expect the round-trip to write back a
page with the template missing — we did not verify that, and it should be
confirmed before the severity here is finalised.
Related defect, filed separately
The
entity not found: fromerror in test C above is a second, independent bug:DESCRIBE PAGEemitsdatabase fromfor datasources that are not a database-over-entity— sometimes with the entity slot blank, sometimes with a microflow name in it. It is
reported separately — see #941. It matters
here only because it blocks test C before the page-parameter guard does.
Workaround
Read the stored model directly, which is read-only and goes through mxcli:
For write safety, prefer
ALTER PAGEwith targetedSET/INSERT/REPLACE/DROPoperations (verified safe above) and never re-executeDESCRIBE PAGEoutputfor a page whose List View has multiple templates.
Diagnostic bundle
Yes —
mxcli-diag-20260820-132332.tar.gz, available on request. Not attached, becauseit contains client model data.
Note on anonymisation
The entity, page, module and microflow names in this report are placeholders. The
defect was found on a private client project; the shapes, counts and command output
above are faithful to the real measurement, only the identifiers are renamed.