Skip to content

DESCRIBE PAGE silently omits List View specialization templates; SHOW REFERENCES and SEARCH do not index their contents #940

Description

@TOFBuck

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:

  1. 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.
  2. 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.
  3. 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):

  1. Domain model in MyModule: a generalization BaseItem, with two specializations
    TypeA and TypeB. A second entity ChildRecord with an association
    ChildRecord_TypeB to TypeB.
  2. Page MyModule.Parent_Edit. Put a List View on it over BaseItem.
  3. On that List View, add two templates (List View → Templates): one for
    TypeA, one for TypeB.
  4. In the TypeA template, put a few text boxes.
  5. 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.
  6. 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.

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