From 69e1601fecfd1a4af2f9efbfd272533d5b202e1d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 9 Sep 2026 08:26:54 +0000 Subject: [PATCH] Draft the BUG-114 upstream issue, carrying BUG-118 as its second reproduction One issue for the two symptoms of the same enclosing-entity walker defect in mdl/backend/pagemutator/mutator.go: a selection-driven data view (Forms$ListenTargetSource, no EntityRef) re-scopes the new widget's binding to the outer entity, and a flow-sourced gallery template drops it. The ledger's BUG-114 header points at the draft; BUG-118's draft already says not to file separately. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw --- CHANGELOG.md | 3 + bug-logs/mxcli-bugs.md | 1 + ...-page-replace-rescopes-to-outer-context.md | 202 ++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 bug-logs/pending-github-issues/bug114-alter-page-replace-rescopes-to-outer-context.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b8eee3e..e30a231 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ moment updating it became a separate chore). One line per change: Kinds: `new` · `fix` · `learn` (a skill/learning) · `process` (rules, templates, CI). Credit the person or project that surfaced the change — the credit line is the thank-you. +## 2026-09-09 +- new(bug-logs): upstream draft for BUG-114 — `pending-github-issues/bug114-alter-page-replace-rescopes-to-outer-context.md`. One issue for the two symptoms of the same `mutator.go` walker defect: `ALTER PAGE REPLACE`/`INSERT` under a selection-driven data view re-scopes the binding to the outer entity (CE1613, invisible to `DESCRIBE PAGE`), and under a flow-sourced gallery template drops it (``, CE0402 — the former BUG-118 draft, now reproduction 2, not filed separately). Cites the exact functions (`findEntityContextInWidgets` → `widgetOwnEntity` → `EntityRef`-only readers) and that `Forms$ListenTargetSource` is written with no `EntityRef` — the toolkit merge queue, from the dashboard-publishing and language-learning conversions + ## 2026-09-08 - fix(bug-logs): re-probed the two workflow blockers on mxcli **v0.21.0** (released 2026-09-06, Mendix 11.13.0) — **both still open**, and BUG-76's diagnosis in this log was wrong. BUG-121 (`PARALLEL SPLIT`): the same script executed through v0.20.0 and v0.21.0 on two throwaway copies produces a **byte-identical** workflow unit (zero diff from `bson dump` after blanking the `$ID` GUIDs), so the runtime behaviour cannot have changed — and the path contents *are* present in the stored BSON on both versions, so the entry's own title ("writes the paths but not their contents") names the symptom, not the mechanism, which is still unidentified. BUG-76 (`DECISION`): not unconditional storage corruption but a **pincer between two spellings** — a bare outcome passes `mxcli check` and makes the model unloadable (`StorageLoadException`, "not a valid EnumerationValueIdentifier"), while a qualified one is rejected by mxcli's own `MDL-WF03` and loads clean via `exec --no-check` with a single `CE0117` for the empty expression; mxcli mandates the spelling the loader rejects and rejects the one it accepts, which implies two independent fixes rather than one. The correction was made on the source project on 2026-09-02 and never promoted here; it is already filed upstream as mendixlabs/mxcli#1031, so it goes into the draft as a comment to post rather than a rewritten body — a topbar-titled portal project · at merge: the three "disputed" `DECISION` notes on master (`mxcli-bugs.md` v0.20.0 clearance table, `learned-workflow-patterns.md` §1 pointer, §8 version table, §21 verdict table) now cite the resolved pincer diagnosis and the v0.21.0 re-probe instead of "shape-dependent, not isolated" — the toolkit merge queue diff --git a/bug-logs/mxcli-bugs.md b/bug-logs/mxcli-bugs.md index a9dd55b..413bc89 100644 --- a/bug-logs/mxcli-bugs.md +++ b/bug-logs/mxcli-bugs.md @@ -4076,6 +4076,7 @@ trusting either comparison's row count on its own. ## BUG-114: `ALTER PAGE ... REPLACE widget WITH {...}` re-scopes an inherited `ContentParams` reference to the page's OUTER data context — reproduced twice, independently, same project **Severity:** High — silent CE1613 build failure, and the app is DOWN until reverted +**Upstream draft:** `bug-logs/pending-github-issues/bug114-alter-page-replace-rescopes-to-outer-context.md` (2026-09-09; carries BUG-118 as reproduction 2 — file once, not twice) **Discovered:** 2026-09-01, re-confirmed independently 2026-09-02, both on the same dashboard-publishing migration project **Reproducible:** Yes, twice, on two different widgets on two different pages diff --git a/bug-logs/pending-github-issues/bug114-alter-page-replace-rescopes-to-outer-context.md b/bug-logs/pending-github-issues/bug114-alter-page-replace-rescopes-to-outer-context.md new file mode 100644 index 0000000..3fcff6e --- /dev/null +++ b/bug-logs/pending-github-issues/bug114-alter-page-replace-rescopes-to-outer-context.md @@ -0,0 +1,202 @@ +**Repo:** `mendixlabs/mxcli` +**Source:** `bug-logs/mxcli-bugs.md`, `## BUG-114` (discovered 2026-09-01, re-confirmed independently 2026-09-02, dashboard-publishing migration project, Mendix 11.12.1, mxcli v0.20.0) and `## BUG-118` (discovered 2026-08-25, a language-learning app conversion, Mendix 11.13.0, mxcli `39c7d94`) — root cause located in the mxcli source at the 2026-09-07 merge review (`mdl/backend/pagemutator/mutator.go`, HEAD `191a0c9`). One issue for both: same walker, two symptoms. +**Status:** DRAFT — not yet filed. File this one; `bug118-replace-in-gallery-template-drops-binding.md` is folded in below as reproduction 2 and must NOT be filed separately. +**Suggested labels:** bug, mdl, pages, alter-page, silent-corruption + +--- + +**Title:** `ALTER PAGE … REPLACE` / `INSERT BEFORE|AFTER` resolve the new widget's attribute bindings against the wrong data context when the target sits under a selection-driven data view or a flow-sourced pluggable list — `mxcli check` and `exec` clean, model breaks at `mx check` (CE1613 / CE0402) + +**Body:** + +## Summary + +`ALTER PAGE … REPLACE WITH { … }` (and the sibling `INSERT BEFORE` / `INSERT AFTER`) resolve +the new widgets' attribute references through `Mutator.EnclosingEntity(target)`. That walk +(`findEnclosingEntityContext` → `findEntityContextInWidgets` → `widgetOwnEntity`) takes an entity +from a container only when its `DataSource` document carries an `EntityRef`. Two common page +shapes contribute no `EntityRef`, so the walk **skips the target's real scope** and keeps +whatever it last saw: + +| Target sits inside | Stored as | Walk yields | Symptom at `mx check` | +|---|---|---|---| +| a **selection-driven data view** (`DataSource: SELECTION `), nested in a page-level data view over another entity | `Forms$ListenTargetSource` — no `EntityRef` | the **outer** page-level entity | `CE1613 "The selected attribute 'Module.Outer.Attr' no longer exists."` — the binding is re-scoped to an entity that does not have the attribute | +| a **gallery / DataGrid 2 template** whose list is sourced by a microflow, nanoflow, or an association without a direct `EntityRef`, on a page with no outer data view | pluggable `datasource` property, no `EntityRef.Entity` | **empty** | `CE0402 "No value specified."` — `DESCRIBE PAGE` shows `ContentParams: [{1} = ]` | + +In both cases `mxcli check --references` passes, `mxcli exec` reports success, and in the +re-scope case `DESCRIBE PAGE` even prints the intended attribute back correctly, so nothing on the +mxcli side shows the damage. It surfaces at `mxbuild` / Studio Pro load, after the write has +landed — on the first project that meant the running app was down until the snapshot was +restored. + +Widgets authored in the same position by `CREATE PAGE` are bound correctly, and a `REPLACE` whose +target is a direct child of the page body is bound correctly too. The defect is specific to the +enclosing-scope walk used by the ALTER PAGE mutations. + +## Environment + +- mxcli v0.20.0 (reproduction 1, both occurrences) and `39c7d94` / 2026-08-25 (reproduction 2); the walker is unchanged at HEAD `191a0c9` (2026-09-07) and the release notes through 0.19.0 carry nothing for it +- Mendix 11.12.1 (reproduction 1), 11.13.0 (reproduction 2) +- macOS and Linux (container) + +## Reproduction 1 — selection-driven data view: binding re-scoped to the OUTER entity (CE1613) + +Page shape: a page-level data view over `Dashboard`, containing a list over its versions and a +selection-driven data view over `DashboardVersion`, which holds a `dynamictext` bound to an +attribute of `DashboardVersion`. + +```sql +create module "BUG114"; +/ +create persistent entity "BUG114"."Dashboard" ( "Name": string ); +/ +create persistent entity "BUG114"."DashboardVersion" ( "PeriodLabel": string ); +/ +create association "BUG114"."DashboardVersion_Dashboard" from "BUG114"."DashboardVersion" to "BUG114"."Dashboard"; +/ +create page "BUG114"."Dashboard_View" ( + title: 'Dashboard', layout: Atlas_Core.Atlas_Default, + params: { $Dashboard: "BUG114"."Dashboard" } +) { + dataview dvDashboard (datasource: $Dashboard) { + listview lvVersions (datasource: association "BUG114"."DashboardVersion_Dashboard") { + dynamictext txtRow (content: '{1}', ContentParams: [{1} = PeriodLabel]) + } + dataview dvSelected (datasource: selection lvVersions) { + dynamictext txtPreviewPeriod (content: 'Period: {1}', ContentParams: [{1} = PeriodLabel]) + } + } +} +/ +``` + +```bash +./mxcli exec bug114-setup.mdl -p Test.mpr +~/.mxcli/mxbuild/*/modeler/mx check Test.mpr # 0 errors — CREATE PAGE bound txtPreviewPeriod correctly +``` + +Now replace the inner widget with the same binding: + +```sql +alter page "BUG114"."Dashboard_View" { + replace txtPreviewPeriod with { + dynamictext txtPreviewPeriod (content: 'Preview · {1}', ContentParams: [{1} = PeriodLabel]) + } +}; +``` + +```bash +./mxcli check bug114-replace.mdl -p Test.mpr --references # Check passed! +./mxcli exec bug114-replace.mdl -p Test.mpr # Altered page — no error +./mxcli -p Test.mpr -c "DESCRIBE PAGE BUG114.Dashboard_View" +# -> dynamictext txtPreviewPeriod (Content: 'Preview · {1}', ContentParams: [{1} = PeriodLabel]) ← looks right +~/.mxcli/mxbuild/*/modeler/mx check Test.mpr +# [error] [CE1613] The selected attribute 'BUG114.Dashboard.PeriodLabel' no longer exists. +``` + +The stored reference is `Dashboard.PeriodLabel` — the page's outer entity — not +`DashboardVersion.PeriodLabel`. Seen twice on the source project on two different pages +(`txtPreviewPeriod` inside a selection data view; `txtVersionMeta` inside a gallery template with +`ContentParams: [{1} = SizeLabel, {2} = UploadedAt]`, both re-resolved to the outer `Dashboard`). + +## Reproduction 2 — gallery template, no outer data view: binding dropped (CE0402) + +```sql +create module "BUG118"; +/ +create persistent entity "BUG118"."Item" ( "Name": string ); +/ +create page "BUG118"."Page_Gallery" ( title: 'Gallery', layout: Atlas_Core.Atlas_Default ) { + gallery galItems (datasource: database "BUG118"."Item") { + template t1 { + container ctnCard { + dynamictext txtName (content: '{1}', ContentParams: [{1} = Name]) + } + } + } +} +/ +``` + +```sql +alter page "BUG118"."Page_Gallery" { + replace txtName with { + container ctnWrap { + dynamictext txtName2 (content: '{1}', ContentParams: [{1} = Name]) + } + } +}; +``` + +```bash +./mxcli check bug118-replace.mdl -p Test.mpr --references # Check passed! +./mxcli exec bug118-replace.mdl -p Test.mpr # Altered page — no error +./mxcli -p Test.mpr -c "DESCRIBE PAGE BUG118.Page_Gallery" +# -> dynamictext txtName2 (Content: '{1}', ContentParams: [{1} = ]) +~/.mxcli/mxbuild/*/modeler/mx check Test.mpr +# [error] [CE0402] "No value specified." at Text 'txtName2' +``` + +Same result with the explicitly qualified form `ContentParams: [{1} = $currentObject/Name]`, which +rules out attribute rooting as the cause. The original template widget (`txtName`, written by +`CREATE PAGE`) was bound correctly; only the REPLACE-introduced widget loses it. Reproduced on the +2026-08-25 build; note that on v0.20.0 a database-sourced gallery may already resolve (see +"Where it is in the code" — `entityFromEntityRef` was extended for association sources), so run +this reproduction with the gallery sourced by a microflow returning `List of BUG118.Item` if the +database form has since been fixed. The selection-driven data view of reproduction 1 fails on +v0.20.0 regardless. + +## Where it is in the code (`mdl/backend/pagemutator/mutator.go`, HEAD `191a0c9`) + +- `Mutator.EnclosingEntity` → `findEnclosingEntityContext` → `findEntityContextInWidgets`: the + recursive walk carries `currentEntity` down and replaces it only when `widgetOwnEntity(wDoc)` + returns non-empty. +- `widgetOwnEntity` = `extractEntityFromDataSource` (reads `DataSource.EntityRef` only) or + `extractPluggableDataSourceEntity` (reads the pluggable `datasource` property's + `DataSource.EntityRef` only). +- A selection-driven data view stores `DataSource` as `Forms$ListenTargetSource` with a + `ListenTarget` widget reference and **no `EntityRef`**, so `widgetOwnEntity` returns `""` and the + walk keeps the outer entity → reproduction 1. +- A flow-sourced list stores `MicroflowSettings` / `NanoflowSettings`, also without `EntityRef`. + `EnclosingDataSourceFlow` (FINDINGS #55) covers the flow case only for the *nearest* data source, + and only where the caller consults it; the gallery-template path in reproduction 2 still came + back empty → ``. +- `CREATE PAGE` does not go through this walk, which is why the same widget in the same position + is bound correctly at page creation. + +## Expected behavior + +The replacement / inserted widget's attribute references resolve against the target's nearest +enclosing data context, exactly as `CREATE PAGE` resolves them in the same position and as +`DESCRIBE PAGE` prints them back. Concretely: + +1. `widgetOwnEntity` (or the walk around it) resolves a `Forms$ListenTargetSource` by following + `ListenTarget` to the referenced list widget and taking **that** widget's entity. +2. Flow-sourced containers resolve through the flow's return type at every level of the walk, not + only for the nearest source. +3. When the walk cannot determine the context, `mxcli check --references` / `exec` should fail + loudly instead of writing an `` or outer-scoped reference — a page mutation that + cannot bind its attribute has no correct output to write. + +## Actual behavior + +Reproduction 1: binding silently re-scoped to the page's outer entity; every mxcli-side read +(including `DESCRIBE PAGE`) shows the intended attribute, and the model fails to build. +Reproduction 2: binding silently dropped (``), visible in `DESCRIBE PAGE`, model fails +`mx check`. + +## Severity + +**High.** Silent through `check --references` and `exec`; in the re-scope case invisible to +`DESCRIBE PAGE` as well. On the first project the failed build overwrote the previous +deployment, so the running app was down until the `.mpr` snapshot was restored. + +## Workaround + +- Do not `REPLACE` / `INSERT` a widget carrying an attribute binding when the target sits under a + selection-driven data view or a pluggable list template. If the same attribute stays bound and + only the text changes, `SET Content = '…' ON ` leaves the existing binding untouched and + is unaffected (the first project's actual fix). +- A genuine rebind has no narrower ALTER PAGE form today — `SET ContentParams = […]` and the + per-index spellings are hard parse errors — so it needs `CREATE OR REPLACE PAGE` or Studio Pro. +- Gate every ALTER PAGE on the real `mx check`, not on `mxcli check --references` alone.