Summary
Found live while building eShop.Catalog_Overview for a phase-1 catalogue plan (a gallery of
product cards with a per-row image, and paging buttons that should grey out at the first/last
page). mxcli v0.18.0 (2026-08-14T20:29:13Z), devcontainer (linux/arm64), Mendix 11.12.2 project.
Both bugs were confirmed with minimal, isolated repros against a scratch page, and both were
cross-checked with mxcli bson dump against the real, underlying Mendix widget schema — the
properties genuinely exist in the Mendix model; mxcli's MDL writer just does not populate them
for these two cases.
Bug 1 — Image widget's imageUrl texttemplate contentparams binding is accepted at check
time and silently dropped on write
create-page.md's own documented idiom for binding a per-row image path is:
pluggablewidget 'com.mendix.widget.web.image.Image' cardImage (
datasource: imageUrl,
imageUrl: '{1}', contentparams: [{1} = PictureUrl]
)
mxcli check --references accepts this with no warning. mxcli exec accepts it too, but the
round-tripped describe page shows the placeholder with no bound parameter at all:
$ mxcli -p app.mpr -c "DESCRIBE PAGE MyModule.ProbePage"
...
image cardImage (ImageType: imageUrl, ImageUrl: '{1}')
ContentParams is simply absent from the output — not [{1} = PictureUrl], nothing. Building the
project then fails:
[error] [CE0720] "Place holder index 1 is greater than 0, the number of parameter(s)." at Image 'cardImage'
What was tried (all reproduce identically)
- The documented numeric-placeholder form above (
imageUrl: '{1}', contentparams: [{1} = X]), in
every property order (contentparams before/after imageUrl:).
- The
{AttrName} shorthand form mentioned in custom-widgets.md's MCP-authoring section
(imageUrl: '{PictureUrl}') — describe shows it did convert the placeholder to {1} form,
but still drops the binding.
- A bare, unquoted attribute reference (
imageUrl: PictureUrl) — silently serialized as the
literal string 'PictureUrl', not an attribute reference.
- A bracket-expression form (
imageUrl: [PictureUrl]) — the whole property is dropped, not just
the binding.
- A generic
Attribute: PictureUrl key alongside datasource: imageUrl — also dropped entirely.
--engine legacy on mxcli exec — identical result.
- Both a non-persistent view entity and a persistent entity as the datasource — identical
result either way, ruling out entity persistence as a factor.
- A control case in the same page/gallery:
dynamictext debugText (content: 'x: {1}', contentparams: [{1} = PictureUrl]) — this one round-trips correctly
(Content: 'x: {1}', ContentParams: [{1} = PictureUrl]), confirming the general
attribute-resolution and contentparams mechanism works; the gap is specific to this
PLUGGABLEWIDGET's texttemplate properties, not attribute binding in general.
custom-widgets.md's own auto-mapping table for third-party widget extraction independently
documents textTemplate as *skipped* -- too complex for auto-mapping, which is consistent with
this being a known-rough edge of the writer, not a one-off.
Impact
Any page using the Image widget's imageUrl (or, by the same mechanism, alternativeText) with a
per-row/per-object dynamic path — the standard way to show a different picture per list item —
cannot build. The failure is loud (CE0720, not silent), so at least it is caught by mxcli check
- a build, rather than shipping a blank
<img>.
Workaround used
None available without an architecture change (the documented fallback — datasource: image with
a System.Image specialization — requires re-seeding every image as a binary object, which was
out of proportion for a page-authoring task). Shipped with a static literal imageUrl instead
(every row shows the same fallback image), recorded as a known stub in the plan's SUMMARY.
Bug 2 — ACTIONBUTTON's Editability / ConditionalEditabilitySettings are not wired through
editable: (or any other property name tried)
Mendix's real Forms$ActionButton widget carries genuine Editability (enum: Always / …) and
ConditionalEditabilitySettings (the expression) properties — confirmed via:
$ mxcli bson dump -p app.mpr --type page --object "MyModule.ProbePage" --format json | grep -A3 Editab
{
"Key": "Editability",
"Value": "Always"
},
...
{
"Key": "ConditionalEditabilitySettings",
"Value": null
}
Writing editable: [SomeBooleanAttribute] on an actionbutton is accepted by mxcli check with
no MDL-WIDGET07 warning (i.e. mxcli recognizes editable: as a real, modeled concept), and
mxcli exec runs without error — but a bson dump immediately afterward shows Editability is
still "Always" and ConditionalEditabilitySettings is still null. The value has nowhere to go.
What was tried
Roughly a dozen candidate property names on actionbutton (active, enabled,
isvisible, editability, activewhen, activecondition, activeexpression,
enabledexpression, clickable, isenabled, isactive, conditionalenabled, disable,
disableexpression) — every one of these other than editable produces an explicit
MDL-WIDGET07 "... is not recognized and will be silently dropped on write" warning at check
time, which is the expected/documented behavior for a genuinely unknown property name. Only
editable is silently accepted as "known" yet has no effect on Forms$ActionButton's
Editability/ConditionalEditabilitySettings fields on write.
Impact
There is currently no way, via MDL, to bind an ACTIONBUTTON's active/inactive state to an
expression (the common "grey out Previous on the first page" pattern). Because MDL-WIDGET07
does not fire for editable: specifically, this fails silently — the property is accepted,
the build succeeds, and the button simply never becomes inactive, which is a worse failure mode
than an unrecognized-property warning would be.
Workaround used
A CSS-only substitute: dynamicclasses (a plain expression property, unaffected by this gap) adds
a .paging-inert class (opacity: 0.5; pointer-events: none;) when the flag is false. This
achieves the same visual/interaction outcome (greyed out, unclickable) without engaging Mendix's
native Editability, so an automated check for the literal HTML disabled attribute will not find
one — a check for the CSS class / computed pointer-events is needed instead.
Suggested fix direction
For Bug 1: either wire contentparams through for textTemplate-typed PLUGGABLEWIDGET properties
generally (matching how content/contentparams already works for native DYNAMICTEXT), or
document the gap explicitly in create-page.md's Image-widget section so the next reader does not
repeat this investigation.
For Bug 2: add a real editable: → Editability/ConditionalEditabilitySettings mapping for
actionbutton, or — at minimum — make MDL-WIDGET07 fire for editable: on widget types where it
has no effect, so the gap is loud instead of silent.
Related (not duplicates)
Summary
Found live while building
eShop.Catalog_Overviewfor a phase-1 catalogue plan (a gallery ofproduct cards with a per-row image, and paging buttons that should grey out at the first/last
page). mxcli
v0.18.0(2026-08-14T20:29:13Z), devcontainer (linux/arm64), Mendix 11.12.2 project.Both bugs were confirmed with minimal, isolated repros against a scratch page, and both were
cross-checked with
mxcli bson dumpagainst the real, underlying Mendix widget schema — theproperties genuinely exist in the Mendix model; mxcli's MDL writer just does not populate them
for these two cases.
Bug 1 — Image widget's
imageUrltexttemplatecontentparamsbinding is accepted atchecktime and silently dropped on write
create-page.md's own documented idiom for binding a per-row image path is:mxcli check --referencesaccepts this with no warning.mxcli execaccepts it too, but theround-tripped
describe pageshows the placeholder with no bound parameter at all:ContentParamsis simply absent from the output — not[{1} = PictureUrl], nothing. Building theproject then fails:
What was tried (all reproduce identically)
imageUrl: '{1}', contentparams: [{1} = X]), inevery property order (contentparams before/after
imageUrl:).{AttrName}shorthand form mentioned incustom-widgets.md's MCP-authoring section(
imageUrl: '{PictureUrl}') —describeshows it did convert the placeholder to{1}form,but still drops the binding.
imageUrl: PictureUrl) — silently serialized as theliteral string
'PictureUrl', not an attribute reference.imageUrl: [PictureUrl]) — the whole property is dropped, not justthe binding.
Attribute: PictureUrlkey alongsidedatasource: imageUrl— also dropped entirely.--engine legacyonmxcli exec— identical result.result either way, ruling out entity persistence as a factor.
dynamictext debugText (content: 'x: {1}', contentparams: [{1} = PictureUrl])— this one round-trips correctly(
Content: 'x: {1}', ContentParams: [{1} = PictureUrl]), confirming the generalattribute-resolution and contentparams mechanism works; the gap is specific to this
PLUGGABLEWIDGET's texttemplate properties, not attribute binding in general.
custom-widgets.md's own auto-mapping table for third-party widget extraction independentlydocuments
textTemplateas*skipped* -- too complex for auto-mapping, which is consistent withthis being a known-rough edge of the writer, not a one-off.
Impact
Any page using the Image widget's
imageUrl(or, by the same mechanism,alternativeText) with aper-row/per-object dynamic path — the standard way to show a different picture per list item —
cannot build. The failure is loud (
CE0720, not silent), so at least it is caught bymxcli check<img>.Workaround used
None available without an architecture change (the documented fallback —
datasource: imagewitha
System.Imagespecialization — requires re-seeding every image as a binary object, which wasout of proportion for a page-authoring task). Shipped with a static literal
imageUrlinstead(every row shows the same fallback image), recorded as a known stub in the plan's SUMMARY.
Bug 2 — ACTIONBUTTON's
Editability/ConditionalEditabilitySettingsare not wired througheditable:(or any other property name tried)Mendix's real
Forms$ActionButtonwidget carries genuineEditability(enum:Always/ …) andConditionalEditabilitySettings(the expression) properties — confirmed via:Writing
editable: [SomeBooleanAttribute]on anactionbuttonis accepted bymxcli checkwithno
MDL-WIDGET07warning (i.e. mxcli recognizeseditable:as a real, modeled concept), andmxcli execruns without error — but abson dumpimmediately afterward showsEditabilityisstill
"Always"andConditionalEditabilitySettingsis stillnull. The value has nowhere to go.What was tried
Roughly a dozen candidate property names on
actionbutton(active,enabled,isvisible,editability,activewhen,activecondition,activeexpression,enabledexpression,clickable,isenabled,isactive,conditionalenabled,disable,disableexpression) — every one of these other thaneditableproduces an explicitMDL-WIDGET07 "... is not recognized and will be silently dropped on write"warning atchecktime, which is the expected/documented behavior for a genuinely unknown property name. Only
editableis silently accepted as "known" yet has no effect onForms$ActionButton'sEditability/ConditionalEditabilitySettingsfields on write.Impact
There is currently no way, via MDL, to bind an ACTIONBUTTON's active/inactive state to an
expression (the common "grey out Previous on the first page" pattern). Because
MDL-WIDGET07does not fire for
editable:specifically, this fails silently — the property is accepted,the build succeeds, and the button simply never becomes inactive, which is a worse failure mode
than an unrecognized-property warning would be.
Workaround used
A CSS-only substitute:
dynamicclasses(a plain expression property, unaffected by this gap) addsa
.paging-inertclass (opacity: 0.5; pointer-events: none;) when the flag is false. Thisachieves the same visual/interaction outcome (greyed out, unclickable) without engaging Mendix's
native
Editability, so an automated check for the literal HTMLdisabledattribute will not findone — a check for the CSS class / computed
pointer-eventsis needed instead.Suggested fix direction
For Bug 1: either wire
contentparamsthrough fortextTemplate-typed PLUGGABLEWIDGET propertiesgenerally (matching how
content/contentparamsalready works for native DYNAMICTEXT), ordocument the gap explicitly in
create-page.md's Image-widget section so the next reader does notrepeat this investigation.
For Bug 2: add a real
editable:→Editability/ConditionalEditabilitySettingsmapping foractionbutton, or — at minimum — makeMDL-WIDGET07fire foreditable:on widget types where ithas no effect, so the gap is loud instead of silent.
Related (not duplicates)
CaptionParams/ContentParams/ShowContentAsweredropped in
datagrid_builder. Same symptom shape (accepted, silently dropped on write), but adifferent code path (grid columns, not a
PLUGGABLEWIDGET's own texttemplate property) — filingseparately in case the fix for Column-level CaptionParams / ContentParams / ShowContentAs dropped in datagrid_builder #547 didn't cover this one too.
alter page … set Editable = [expr]corrupts the project: StorageLoadException, .mpr will not load (CREATE/INSERT path is fine) #851 (closed) —alter page ... set Editable = [expr]corrupting the project. Also aboutEditability, but on
TEXTBOX(an input widget where Editable is otherwise wired) viaALTER PAGE, and the failure mode there is project corruption, not a silent no-op onCREATE PAGE.