Repository navigation
v0.29.0
[0.29.0] - 2026-10-30
Headline: Write what the project's own Mendix version stores, and commit it the way Studio Pro does. Every write is now checked against the element types and property shapes of the project's Mendix version, so a statement 9.x or 10.x cannot store is refused by check -p instead of leaving a project Studio Pro cannot open, and mxcli git commit / git doctor keep a plain-git history in the shape Studio Pro expects. Alongside it: workflows, pages and Java actions gain the settings a rewrite used to reset, alter microflow edits inside loop bodies, the debugger works end to end, and commands on large MPR v2 projects open only the files they need.
Added
mxcli git commit -m … -p app.mpr— commit the way Studio Pro does (#1669) — Studio Pro's Commit is more thangit commit: it keeps the ContentsHash index in step, stages exactly the files a Mendix repository ships, and attaches the mx_metadata note. The new command is that sequence in one line: mismatched hashes are repaired from the files on disk first (MISSINGandORPHANentries have no automatic repair and refuse the commit), everything is staged and the files Studio Pro never commits (project-settings.user.json,*.mpr.lock,*.mpr.bak, and the project's own.mendix-cache/,deployment/,theme-cache/,.mxcli/beside the.mpr— a folder of the same name further down, such asresources/deployment/, is committed) are unstaged again,git commitruns with the caller's message and identity, and the mx_metadata note is computed from the new commit and attached, so Studio Pro can version-check the revision and show what changed.--pushpushes the branch and the notes ref together (git pushalone loses the note the next time Studio Pro fetches);--dry-runreports what it would commit without committing — and without repairing anything, hash drift included, because a dry run writes nothing: it stages into a copy of the index, so what the user had staged is left as it was. The commit is refused while Studio Pro has the project open (.mpr.lock) — honouring the sameMXCLI_ALLOW_STUDIO_PRO_OPEN=1override as every write — and during an unresolved merge, whichgit add -Awould otherwise commit with its conflict markers. Docs: "Working Outside Studio Pro" › One commit, all the steps.mxcli git doctor [-p app.mpr] [--fix]— audit a repository for everything a plain-git history misses, and repair it (#1669) — a repository committed only with git drifts from what Studio Pro expects in four ways, each invisible on its own: the local git config Studio Pro writes is absent (core.autocrlf=Falsekeeps a checkout from rewriting line endings inside.mxunitfiles on Windows;mendix.commits-since-gcandmendix.lineEndingResetDoneare its own bookkeeping), the remote is SSH which Studio Pro cannot use (HTTPS only), commits have no note underrefs/notes/mx_metadata(history shows(unknown), the version check fails), and a malformed note Studio Pro cannot read at all.doctorreports all four in one read-only pass and exits 1 while an issue remains, so it can gate CI.--fixsets the config keys, rewrites SSH remote URLs (git@host:org/app.git,ssh://…) to HTTPS — judged as configured, so aurl.<base>.insteadOfrule in the user's git config (https →git@is a common one) is reported rather than "repaired" on every run — and backfills notes: computed from the model with-p(the same enginegit noteuses), or a template note with a--versionModelerVersion where the model at a commit cannot be read (MPR v1 history, a revision without the.mpr); with neither, the newest valid note in history supplies the version. Notes Studio Pro wrote are never touched, with or without--fix;--fixdoes not push. A clone whose notes ref lacks the remote's notes —git clonenever fetchesrefs/notes/*, so every fresh clone and CI checkout — is reported as exactly that, with the fetch command, rather than as a history of unannotated commits;--fixfetches the notes first, as a fast-forward only. Docs: "Working Outside Studio Pro" › Auditing a repository.- Workflows say what Studio Pro lets them say — a user task takes a
task name '…'clause (what the task inbox shows, until now always the caption), and the workflow's display and description and a task's name and description take template parameters,display 'Approval for {1}' with ({1} = $WorkflowContext/Title), in CREATE and ALTER. A timer boundary event takescaption '…', and a non-interrupting timer can recur:repeat every 1 day at most 3 times.alter workflow … set (Annotation: '…')sets the workflow's note, and… on <activity>an activity's. Adescribe→create or modifythat would still reset a setting MDL cannot state is refused, naming the setting, instead of reporting "Modified workflow". - MDL-WF20: a user task whose page cannot complete one of its outcomes — Mendix adds no buttons to a task page, so a page that only shows the task passes
mx checkand the build, and every instance then waits at the task forever.checknow warns per task, listing the outcomes nocomplete taskbutton, or button whose microflow reachesset task outcome, can complete. alter microflowedits inside a loop body, andalter … replace body ofreplaces just the body (ako#1693) —create or modify(undermdl 1) andalter microflowsplice an activity inserted, dropped or moved inside a loop body, where they used to refuse and point atreplace loop, which re-mints every element ID in the loop.replace body of <loop>is the explicit fallback. A fragment's@annotationcan now attach a statement to a note already in the flow by its text (ako#1695), and the decision analter … insertproduced can be dropped or replaced again (ako#1694).- Return value mappings on a button's flow call (#977) —
call microflow M.Get returns (Brand = $ActionReturnValue/Brand, $s = $ActionReturnValue)writes and describes Studio Pro's Return value mappings (Mendix 11.5), and a rewrite keeps stored ones. alter app security (AdminPassword: '…')(ako#1259) — CE0129 "Administrator password has not been set" could only be resolved in Studio Pro.create java action … extra code $$ … $$(ako#1702) — the third part of a.javafile Studio Pro keeps when it regenerates one.describe java actionprints it, so a helper method travels with the action to another project. The written file now also has the class javadoc mxbuild writes (ako#1700), so a rewrite no longer leaves a pair of unrelated VCS diffs.- Page and widget settings that had no MDL spelling — a rewrite used to reset each of these to a default: a page's own
DesignProperties: ( … ), typed against the native theme on a native page (the web one turned a native colour option into a custom colour); a dynamic text'sNativeTextStyle: Heading3; a tab page'sBadge:(ako#1653); a text area'sNumberOfLines:andAutocomplete:; a responsive layout's scroll-containerLayoutMode: Sidebar(ako#1703), which made a copied Atlas sidebar layout a Headline one; a show page action's Number of pages to close; and an import mapping call's input object and commit mode,import from mapping M.IMM($Json) (Parameter: $Obj, Commit: No) all;, without which a mapping with an input object could not be called at all.
Changed
docker checkchecks the project as stored by default, and says which CE0463mxcli fix widgetsclears (ako#568, #646) — this changes the default. Until nowdocker checkranmx update-widgetson its temporary copy beforemx check, so it validated a widget-normalised model: a project whose stored widgets were stale (CE0463 "The definition of this widget has changed") got "0 errors" and exit 0, and thenmxcli run --localand MxBuild, which build the project as stored, refused it. Now the verdict and the exit status are the stored project's. When the stored project has CE0463, the same copy is re-checked aftermx update-widgetsand each CE0463 is labelledstale widget definition — mxcli fix widgets fixes itorpersists after update-widgets, with themxcli fix widgets -p <app>.mprcommand and the error count after the resync. A project without CE0463 is checked once, as before.--update-widgetsrestores the old behaviour (check only the normalised copy);--no-update-widgetsis still accepted, and checks as stored without the re-check. Measured on Mendix 11.13.0 with a blank app whose Data grid 2 package gained a property: the old default reported 0 errors, the new one 11 errors, all labelled stale; aftermxcli fix widgetsit reports 0. The project is still never modified.docker build's pre-build check is unchanged and still runs on a normalised copy.
Fixed
playwright checkno longer fails a page checked by the app's own host name behind a proxy (ako#1800) — withhttps_proxyset and an app checked ashttp://frontend.local:8180/(an/etc/hostsname for127.0.0.1), a page that rendered failed on two console errors,WebSocket connection to 'ws://frontend.local:8180/mxdevtools/' failed: … Unexpected response code: 502, while the same check on127.0.0.1passed. The runtime serves its dev channel on that name; the 502 came from the proxy, because Chromium sendsws://to the HTTPS proxy andno_proxylisted only the loopback names. The browser thatplaywright check,run --page-checkandrun --screenshotstart now reaches a host that resolves to this machine directly. No console error is ignored: the channel connects, and a genuine console error still fails the page.- Published OData entity sets, OData actions and older domain models have the property names Studio Pro writes (ako#1805) — on a Mendix 11.14.0 project
mxcli fix property-setsreported sevenMIXEDnames and could fill none of them. An entity set published without stating its modes was written withoutReadMode,InsertMode,UpdateModeandDeleteMode, and an action whose microflow takes no parameters withoutParameters; they are now written, as the values Mendix already read the missing ones as (read from the database, changes not supported, no parameters), so the service behaves as before anddescribenow prints the four modes. The domain-model names (LocalizeDateon a DateTime attribute, the four system-attribute flags on an entity without a generalization) are not left out by any current statement: they belong to entities an older mxcli wrote, which every later write of the domain model kept as they were. Both are now filled from values measured withmx converton 10.24.24, 11.13.0 and 11.15.0, on the next write of the document or bymxcli fix property-sets. Runmxcli fix property-setsonce to complete what an earlier mxcli wrote. - A retrieve over a self-reference is the one object Mendix makes it, and a list use of it is refused by
check -p(ako#1793) — for a Reference from an entity to itself (M.Order_Parent),create microflowtypedretrieve $P from $Order/M.Order_Parentas a list ofM.Orderunless$Pwas later used as an object, so$n = count $P;passedcheck -pandexecand failedmx checkwith CE0013 "Input variable 'P' must be of type 'List'.". Mendix follows a self-reference from its FROM end: a Reference gives the one object, a Reference set the list. The full build,alter's splice andcheck -pnow take that one rule, from the entity and from a specialization of it alike, andcheck -pandexec's pre-flight report MDL-RETRIEVE01 for the one object a Reference gives from its FROM entity — a self-reference or not — taken by an aggregate (CE0013), a list operation other thanrange(CE0097), aloop(CE0100) or a list parameter (CE0117).seton a self-reference's object is refused likeseton any object (CE7247); the Change list Replace it used to be written as passedmx checkonly because mx check does not type a Change list's variable. Measured on 11.13.0: before,count $Ppassedcheck -pandexecand was CE0013; nowcheck -prefuses it, and the object uses and the Reference set's list uses build at 0 errors. - Pages, navigation, module settings, scheduled events, database connections, business events, REST clients and view entities are refused by
check -pbelow what their write needs (ako#1811) — the same sweep found document shapes the writers produce in a type or property newer than the project, with no check-time gate or with one below it: snippet parameters (9.21),alter page … add parameters(9.4), page variables (10.20, their default value),action: complete task(9.19) and the other workflow button actions (9.0.2), a menu itemIcon:(9.20), progressive web app settings (9.0.3), a native profile's home page (9.4), a not-found page (10.13), JAR dependencies (10.0) and their exclusions (10.12),create scheduled event(9.12),create database connection(10.0; with aquery, 10.12),create business event service(9.24), and on a consumed REST service basic authentication (10.2), any operation (10.4: its method and response handling), query parameters (11.0) and an OpenAPI document (10.21).create view entitywas gated at 10.18, where view entities arrived, but mxcli stores the query in a separate source document that is a 10.21 type: on 10.18 to 10.20check -ppassed it and the write refused it. Its floor is now 10.21. Each floor is pinned to the type and property data the write refuses on; thesdk/versionsrows that said otherwise (database connector 10.6, business events 10.0) now hold it, and mx 9.24.30 loads a business event service mxcli writes. - A workflow parameter, a user task and the other workflow parts an older Mendix stores differently are refused by
check -p, not part-way throughexec(ako#1811) — past the workflow's own 9.0.2 (#1809), what a workflow states has later floors, which the write enforced and no gate named. Measured on 9.x projects whose recorded version was set below each floor: every workflow with aparameteris refused below 9.18 (Workflows$Parameter.Name) and everyuser taskbelow 9.19 (Workflows$UserTaskOutcome.Value); ajump toneeds 9.0.5, acall workflowactivity 9.6 (with parameter mappings 9.18), anoverview page9.11, an annotation 9.15 and an event sub-process started by an interrupting notification 11.10.create workflowandalter workflownow report each with MDL-VERSION01. Theuser taskrow ofsdk/versionssaid 9.0.0, soshow featureson 9.0 to 9.18 listed user tasks the write could not store. - Loops,
show pagewith arguments, queued calls andexecute database queryare refused bycheck -pbelow their Mendix version (ako#1811) — the sweep behind the previous entry listed every$Typethe converters construct against the Model SDK's type data and found more flow activities the write refused with no check-time gate:loop … in $Listandwhile(9.0.4: before it, a loop stores its list on itself),show page … (Param = $Value)(9.7),call microflow/call java action … in queue(9.10),execute database query(9.24) and itsconnection ( … )arguments (11.1). They are gated increate/alter microflowandnanoflowlike the previous entry's. Thesdk/versionsrows for the database query said 10.6 and 11.0; they now hold the type floors, 9.24 and 11.1, and mx 9.24.30 loads the action, soshow featureson 9.24 lists it. send rest request,range,call external action,transform … withandfind/filter … whereare refused bycheck -pbelow their Mendix version, not part-way throughexec(ako#1811) — none of them had a check-time gate, somxcli check -ppassed them and the write refused them ("this Mendix 9.24.30 project cannot store Microflows$RestOperationCallAction (Mendix 10.1.0+)") after the statements before it, or, with--continue-on-error, ran on without that microflow.check -pandexec's pre-flight now report MDL-VERSION01 naming the statement and the version, increate microflow/nanoflowand in whatalter microflow/nanoflowinserts, wherever it sits:find/filter … where(or a condition that is notMember = value) 9.0.3,call external action9.19 (with arguments 10.2),range9.24,send rest request10.1 (with arguments 10.2, a result variable 10.4,body $Var10.5) andtransform … with11.4. Each floor is the type's introduction in the Mendix Model SDK, pinned by a test to the data the write refuses on.send rest requestis gated at 10.1 although mx 9.24.30 loads the action: the consumed REST service it calls is a 10.1 type too, so a 9.24 author cannot set one up. Afindon a String the statement declares is a Stringfind(), not a list operation, and is not gated.create workflowis refused bycheck -pon Mendix 9.0.0 and 9.0.1, not part-way throughexec(ako#1809) — theworkflows basicfloor was 9.0.0, whileWorkflows$Workflowarrived in 9.0.2 (the Mendix Model SDK's version data), and onlyalter workflowapplied it. On 9.0.0 or 9.0.1,create workflowandcreate or modify workflowpassedcheck -pand the write then refused them ("cannot store Workflows$Workflow (Mendix 9.0.2+)"). The floor is now 9.0.2, pinned by a test to the same data the write refuses on, and all three statements report MDL-VERSION01 incheck -pandexec's pre-flight.alter workflow's hint said "upgrade your project to Mendix 9.12+", a version the gate never stood for; it names none now, and the message states the floor.- A catalog refresh on an MPR v2 project opens only the files that changed (ako#1804) — every refresh read every
.mxunitof the project, 4,753 files on a large app, after every save; on Windows each open is scanned by the virus scanner. mxcli now keeps a compressed copy of the units in.mxcli/cache/unit-contents.dband reads a unit from its file only when the file's size, modification time or recorded hash has changed, so a refresh after a save opens one file or none. The store is git-ignored and safe to delete. - Changing one entity no longer re-describes its whole module in the source index (ako#1803) — an incremental source rebuild treated an entity as changed whenever anything in its module's domain model did, so one new attribute re-described every entity of the module and every document using any of them: 346 documents for an unreferenced entity in a 154-entity module of a 4,753-unit app. An entity's basis is now its own subtree, and the same edit re-describes 1. A change to an association or annotation still re-describes the module's entities.
- Workflow actions an older Mendix does not have are refused by
check -p, not part-way throughexec(ako#1787) —notify workflow(10.0),get workflowsandget workflow activity records(10.4), and the other workflow actions of a microflow (call workflow,set task outcome,open user taskandopen workflow9.0.2,workflow operation abortandrestart9.2,pauseandcontinue9.3,get workflow data9.10,retryandunpause9.12) had no check-time gate:mxcli check -ppassed the script, and the write then refused it ("this Mendix 9.24.30 project cannot store Microflows$NotifyWorkflowAction (Mendix 10.0.0+)") after the statements before it, or, with--continue-on-error, ran on without that microflow.check -pandexec's pre-flight now report MDL-VERSION01 naming the statement and the version, wherever the action sits: a branch, a loop, an error handler. Each floor is the type's introduction in the Mendix Model SDK, and a test pins thesdk/versionsrows to the same data the write refuses on (canon.TypeIntroduced), so the two cannot disagree. Measured on 9.24.30: before,check -ppassed andexecrefused at write time; nowcheck -preports each,execwrites nothing, andApp.mpris byte-identical. On 10.24.24 the script executes as before, with 0 errors. alter microflowandalter nanofloware version-gated likecreate(ako#1787) — no version gate reached what aninsertorreplacesplices in, somxcli check -ppassed analter microflow … { insert after … begin $Wfs = get workflows for $Obj; end; }on 9.24.30, and the write refused it ("cannot store Microflows$GetWorkflowsAction (Mendix 10.4.0+)"). What an alter inserts is now gated as the same statements in acreate microfloworcreate nanofloware: the workflow actions,send email(11.13), a lock or unlock naming its workflow (10.0) andsynchronize unsynchronized(9.4).check -pandexec's pre-flight report MDL-VERSION01, andexecwithout the pre-flight refuses the statement before reading the stored flow. A drop, or an insert of nothing gated, is not affected.mxcli debug enable,statusandbreakno longer say continuing and stepping arrive "in a later slice" (ako#1813) — they work since ako#1782;enablenow namesdebug break, andstatus/breaknamedebug continue. The debugger proposal's protocol table now records the measured shapes:add_breakpointrequiresconditionandcontinuetakes{debug_id}.mxcli debug breaksets the breakpoint, and nomxcli debugcommand reports success when the runtime refuses it (ako#1782, #1676) —debug breakwithout--ifsentadd_breakpointwith nocondition, which Mendix 11.13 and 11.15 (both measured) refuse with{"message":"Missing property: condition","status":2}and register nothing; mxcli printed "Breakpoint set",debug breakslisted it, and the microflow ran to the end without pausing. The runtime answers a refused debugger request with HTTP 200, and mxcli read only the HTTP status.conditionis now always sent (empty for an unconditional breakpoint), and every debugger command fails with the runtime's message when the reply's status is non-zero — a bad--ifexpression, an unknown activity or microflow, a variable that does not exist, or a session token the runtime no longer knows (with themxcli debug enableremedy). Verified on a running 11.15 app: the breakpoint now pauses the flow, andpaused,stepandcontinuedrive it to the end.mxcli debugprints the runtime's reason for a refused request without the usage text after it (ako#1782) — once adebugsubcommand's arguments are accepted, an error is the runtime refusing a request or no flow being paused, not a usage mistake, and thirty lines of flags buried the reason. A missing argument or unknown flag still prints the usage.mxcli debug inspectprints a String or enumeration variable's value instead of{}(ako#1782, #1676) —inspectasks the runtime'sget_object, which takes only an object variable and refuses a primitive ("The variable 'Greeting' is not a Mendix object."); the refusal's empty result was printed as the value. A primitive's type and value are in the paused flow's state already, andinspectnow prints them from there; an object variable still shows its members.mxcli debug continueresumes the paused flow instead of leaving it paused (ako#1782, #1676) — it sentcontinuewith nodebug_id, which the runtime refuses ("Missing property: debug_id", measured on Mendix 11.13 and 11.15), and printed "Continued." while the flow stayed paused untilcontinue --all. It now resumes the paused flow by itsdebug_id: the only paused one, or the one named with the new--flow <debug_id>, asstepandinspectalready did.- Rebuilding a catalog that has a source index describes only what changed (ako#1790) — once a project had a source index (
refresh catalog full source), every later rebuild described every document again. That includes the rebuildssearchandshow referencesstart after each save. On a 4,753-unit app that was 38 s per rebuild, and much longer on Windows before #1789. A rebuild now re-describes the documents whose unit changed (an entity's unit is its module's domain model) and the documents whose references name one of them. The rest are carried over from the cache. After adding one attribute, the same app rebuilds in 11 s: 3,525 rows reused, 193 described, and the index is byte-identical to a forced full rebuild. A change outside the described documents (a folder, a module, the project settings, a Java action), a cache written by another mxcli build, andforcestill describe everything. The cache records each unit's content hash and container, so a document moved into another folder is described again too. - Commands on an MPR v2 project open only the files they need (ako#1791) — on a 4,753-unit app,
show modulesopened 4,511 unit files,describe microflow2,996 anddescribe page3,176, in every process. The commands read every folder to build module paths and every microflow to name or find one, andshow modulesdecoded every page, snippet, flow, constant and Java action just to count them. Each open is cheap on macOS and is scanned by Defender on Windows, so this added time to every command an agent runs. The unit index in.mxcli/now also holds each unit's name andExcludedflag, keyed by content hash like its type, so it never goes stale. Folders and microflows are named from the index, a microflow is found by name and read by ID, andshow modulescounts from unit types. The same commands now open 509, 93 and 274 files, with output identical across three projects and all 229 page describes. The index moves tounit-index-2.idx, so an older mxcli on the same project keeps its ownunit-types.idxinstead of the two rebuilding each other's. refresh catalog full sourcereads each unit file once instead of millions of times (ako#1789) — the source index describes every document, and each microflow describe found its microflow, and every microflow it calls, by listing every microflow of the project from disk. On a 4,753-unit MPR v2 app one refresh opened 7,532,649.mxunitfiles: 5.5 minutes on macOS, and 90 minutes or more on Windows, where Defender scans every file open. The catalog build now keeps the units it reads in memory, and a describe reads its microflow and the microflows it calls by ID. The same refresh opens 4,753 files and takes 31 s, and its source text is byte-identical. The rebuilds thatshow referencesandsearchrun on a project with a source index are the same build, so they speed up too.- Moving a Java or JavaScript action to another module takes its source along —
move java action A.X to Bmoved the document and leftjavasource/a/actions/X.javabehind (likewise a JavaScript action's.js). The build still succeeded, but the app called a generated stub that throws "Java action was not implemented", anddescribeprinted a placeholder body that re-executing would have stored. The source now moves to the target module's directory, with a Java source'spackageline rewritten exactly as mxbuild regenerates it; an occupied destination refuses the move before anything changes. - Writing an MPR v1 project through the Go library no longer hangs — on a project whose contents live in the
.mpr(Mendix below 10.18),codec.Store.SaveUnit,FlushUnitsandmodelsdk.Model.Flushnever returned: the write transaction read the stored unit through the reader's single pooled connection, which the transaction itself held. It now reads through the transaction.mxcli execwrites through a different path and was not affected. - Re-running an OData client script from a checkout at another path no longer rewrites the client (ako#1499) — a relative
MetadataUrlsuch as./contracts/f1-metadata.xmlis stored as the absolutefile://URL of the checkout that ran it, andcreate or modify consumed odata servicereplaced that URL with its own on every run. The same unchanged script, run from another machine, a moved folder or a git worktree, rewrote every client: 5 of the 20 writes of a full re-exec in the reported project. The stored URL is now kept when it names the same project file, and the contract is read from this checkout's file. The stored form stays absolute:mx checkaccepts a relative value, but it also accepts a dead absolute path, so it shows nothing about what Studio Pro's metadata editor accepts.describeprints a stored URL inside the project directory as./contracts/…, so a script generated from the model carries no machine path. Measured on 11.13.0: the same script run after moving the app, and from a copy, reported the client unchanged (before: "Modified OData client"), withmx check0 errors. - On an MPR v1 project, a unit write updates
Unit.ContentsHashwith the contents (ako#1159) — below Mendix 10.18 the unit contents live in the.mpr, and every write replaced a unit'sContentsbut left itsContentsHashdescribing the old bytes; an inserted unit got an empty hash.mx checkand MxBuild never read the column, so nothing failed, but Studio Pro reads it to detect what changed. Studio Pro fills it on every v1 unit with the same formula as v2,base64(SHA-256(Contents)): 308 of 308 units of a fresh 9.24.30 app. Update, insert and the transactional write now store it.mxcli fix hashescovers v1 too: it compares each hash with the contents in its row, and--repairrewrites the ones an earlier mxcli left stale.execanddocker checkstill verify v2 only, because on v1 that reads every unit. Measured on 9.24.30:create entitypluscreate microflowleft 2 stale rows before the fix and none after,mx check0 errors, andfix hashes --repairrepaired the stale copy. - Workflow activities and events an older Mendix does not have are refused up front (ako#1774) —
mxcli check -pandexec's pre-flight report MDL-VERSION01 before anything is written, naming the clause:wait for notificationbelow 10.0,wait for timerbelow 10.6, aboundary event timerof no kind below 10.14,boundary event [non] interrupting timerbelow 10.20, andlock workfloworunlock workflownaming a workflow below 10.0. Each floor is the type's own introduction in the Mendix Model SDK, and the write refuses the type itself too. Before, a workflow withwait for notificationwas written to 9.24.30, and the project did not load ("TypeCacheUnknownTypeException … Workflows$WaitForNotificationActivity"). Measured on 9.24.30 (refused, and the project is byte-identical) and on 10.24.24 and 11.13.0 (written, 0 errors, as before). - A type newer than the project is refused instead of making the project unloadable (ako#1774) — the version data held property floors only, so no write compared an element's own
$Typewith the project's version.execreported success, and thenmx checkand Studio Pro could not load the project: "TypeCacheUnknownTypeException: The type cache does not contain a type with qualified name …". This shipped four times (#1754, #1209, #1163, #1771), each fixed for its one type. Every type's introduction version is now taken from the Mendix Model SDK (modelsdk/canon/mendixmodelsdk_type_versions.json, extracted from mendixmodelsdk 4.117.0 bygen_type_versions.go). Every unit write refuses an element whose type the project does not have yet, wherever it sits in the unit, naming the type, its version and the project's: "this Mendix 9.24.30 project cannot store Microflows$GetWorkflowsAction (Mendix 10.4.0+)". The check runs after the older shapes are written, so the parallel split's end marker and user tasks are still lowered, not refused. Measured on 9.24.30: a microflow withget workflowsmade the project unloadable before. Now the write is refused, and the project is byte-identical afterwards, with 0 errors. 23 Studio Pro-authored projects from 9.1.1 to 11.16.0 hold no type the floor refuses. The SDK's deletion versions are not enforced, because a type it renames keeps its storage name. - Documents written to Mendix 10.24 below 10.24.24 have the property names Studio Pro writes (ako#1505, #1595) — on 10.24.18 a nanoflow re-created with
dropandcreatelackedExportLevelandReturnVariableName, somx diffand Studio Pro's change view threw "Objects with ID … do not have the same properties". A new microflow lacked the aggregate's four expression properties, a delete's error handling, a while loop's caption and a retrieve's XPath constraint, and a new entity its image properties. mxcli fills these from a table of values measured withmx convert, and the table had been measured from 10.24.24 up only; that version was then treated as the one that introduced each property. Measured again on 10.24.0 and 10.24.18, 94 of its rows now apply from 10.24.0, including open user task, REST operation call, timer boundary event and business event service properties. Runmxcli fix property-setsto complete the documents an earlier mxcli wrote. mxcli fix property-setsno longer reports a project complete when an element lacks a property the others of its type carry (ako#1505) — on 10.24.18 it said "Every unit already has the property names Studio Pro writes" for a nanoflow withoutExportLevelwhilemx diffthrew on it, because it knew only the properties its measured table holds for the project's version. Studio Pro writes the same property names on every element of a type, so the command now also lists each name some elements of a type carry and others lack, asMIXED <type>.<key>with the units concerned, and exits 1. It does not fill those: no value measured on that Mendix version says what to write.- An
alter microflowfragment can name a member of a list operation's, a Java action's or a self-reference retrieve's output (ako#1777) —alter microflow … { insert after … begin change $First (Status = 'Seen'); end; }, with$First = head $Linesin the stored flow, was refused with nothing written: "cannot qualify member "Status": the entity its variable holds is not known here". The same for a member of any stored filter, sort, tail, union, intersect, subtract, range, head or find output, of a Java action's result, or of a retrieve over a self-reference, thoughcreate microflowtypes them all. A fragment now starts from those types, taken from the same code the full build uses: a list operation's output has its input list's type (an element of it for a head or find), a Java action's result its declared return type (for a list of its type parameter, the list it is given), and an aggregate the primitive the full build declares. A retrieve over a self-reference holds the object the reference holds (the list, for a reference set): the stored retrieve records no direction, and Mendix follows it from the FROM end — measured on 11.13.0, a change on it builds and a count of it is CE0013. A name two origins give different types stays untyped, its member refused. Measured on 11.13.0: seven alters refused before; all written after, mx check 0 errors, describe → exec "Unchanged". - User-task features an older Mendix cannot store are refused up front (ako#1771) —
mxcli check -pandexecreport MDL-VERSION01 before anything is written, naming the clause. The floors are group targeting (targeting groups …) 11.2, a multi-user task 9.22,decide by majorityorthreshold10.0,await all users10.2, anddecide by microflow10.3. Before, group targeting was written on 10.24 and failedmx checkwith CE1859. The others were refused only at write time, after the statements before them were written. Measured on 9.24.30 and 10.24.24 (each refused, nothing written) and on 11.13.0 (all written, 0 errors). alter workflow … set (Targeting: …)changes a user task's targeting on Mendix 9 to 11.1 (ako#1771) — it reported "Altered workflow" and changed nothing. Before 11.2 a user task stores its targeting under another key, and the edit only replaced a key that was already there. The edit now replaces the stored targeting, whichever key holds it, and the write stores it in the version's shape. Measured on 9.24.30 and 10.24.24:describeshows the new targeting, with 0 errors. 11.2 and later are unchanged.- A workflow with a user task no longer makes a Mendix 9 or 10.0–10.11 project unloadable (ako#1771) —
execreported success, thenmx checkand Studio Pro could not load the project at all: "TypeCacheUnknownTypeException: The type cache does not contain a type with qualified name Workflows$SingleUserTaskActivity". mxcli wrote a user task as aSingleUserTaskActivityorMultiUserTaskActivity, types introduced in 10.12. Before 10.12 both are aWorkflows$UserTask, as Studio Pro 9.24 stores it. Its completion says which kind it is, and holds a multi-user task's rule, participants and, from 10.2,await all users. That is what is written now, forcreate,create or modifyand a taskalter workflowinserts.describereads a multi-user task in that shape, andcreate or modifyno longer resets its rule silently. What the older type cannot hold is refused, naming the task: a multi-user task below 9.22,decide by majorityorthresholdbelow 10.0,decide by microflowbelow 10.3,await all usersbelow 10.2, and a boundary event on a user task below 10.14. Measured on 9.24.30 and 10.11.0: 0 errors,mx convertchanges nothing, anddescribe→execreports the workflow unchanged. Converted up to 10.24, the tasks are the ones mxcli writes there directly. 10.12 and later are unchanged. - A user task keeps its targeting on Mendix 10.12 to 11.1, including 10.24 (ako#1771) — every user task mxcli wrote there failed
mx checkwith CE1859 "XPath constraint is required", including tasks targeted by a microflow and multi-user tasks.execandmxcli checkwere clean. mxcli stored the targeting asUserTargeting, which Mendix introduced in 11.2. The older versions read the task as having no targeting at all, andmx convertreplaced it with an empty XPath constraint. Before 11.2 the same fact is aUserSourceholding the same value, measured by converting Studio Pro-authored 9.x workflows up to 10.24 and 11.13. That is what is written now, for users by XPath, users by a microflow, and no targeting. Group targeting is 11.2 and is refused below it, naming the task. Measured on 10.24.24: 0 errors,mx convertchanges nothing, anddescribe→execreports the workflow unchanged. 11.2 and later are unchanged. - A Timeline enumeration the widget hides is refused when set to a non-default value, instead of failing the build (ako#1762, #1668) — a hidden pluggable-widget property must hold its default, or mx check reports CE0463 "The definition of this widget has changed".
mxcli checkalready refused this for the one Timeline hide rule it could read (groupEvents: false), but it read only 2 of the 6 (widget describe timeline: "2 of 6 editor hide-rules recognized"). SocustomVisualization: true, groupByDayOptions: 'dayMonth'andgroupByKey: 'day', groupByMonthOptions: 'monthYear'passedcheckandexecand then failed mx check. The editorConfig's other rules sit in shapes the extractor did not read: aswitchongroupByKeywithcase/defaultarms, and a ternary that terser folds into theswitch(…)head, where the head's paren was taken for a conditional group. Both are read now, as are fall-through and grouped labels, and anif(…)head written the same way (HeatMap'splayground). Timeline is 6 of 6 (3.1.1, 3.2.2 and 3.2.3), and each hidden enumeration gets the verdictgroupEventsalready had: an MDL-WIDGET10 error when set to anything but its default, whichexecrefuses before writing; a warning at its default; written at its default when left out.describeno longer prints a hidden property that holds its default, so its own output re-checks without warnings. MDL-WIDGET10 now says "is none of "day", "month"" for a default arm instead of "matches". The warning the reporter saw on hiddentitle/description/timeIndicationcame from a hand-written fallback table that listed only the text templates of that same hide. Measured on Mendix 11.13.0 with Timeline 3.2.2, one widget per variant: all six hidden variants were CE0463 before, all three controls 0 errors, andchecknow refuses exactly those six. The corrected pages build with 0 errors under--no-update-widgets, and describe → exec reports them unchanged. The File Uploader shape of ako#258 (a ternary-wrappedhidePropertiesIngatingcreateImageAction/createFileActiononuploadMode) was already read via the else-if chain support of #1583, and is now pinned by a test against File Uploader 2.5.0. - An activity edited by
create or modifykeeps its element IDs (ako#1761, #1667) — re-runningcreate or modify microflow|nanoflowwith only a filter's expression changed replaced the activity: the activity, its action and its operation all got new$IDs, while a decision whose condition changed the same way kept its own.check,mx check,diffanddescribeall looked fine, but Studio Pro compares and merges by$ID, so it showed the filter as one activity removed and another added, and a teammate's edit of the same activity on another branch became a conflict. An activity replaced by one of the same kind (the same action) is now edited in place: it keeps its$ID, its place in the flow and its size, and so do its action and every element under it that pairs up — a member change by its attribute or association, an argument by its parameter, a nested element by its key and type. A removed member's$IDgoes onto no other member; a different operation (afindwhere afilterwas) is new. This covers a filter or find expression, a retrieve'swhere, change and create member values, call arguments and any other same-kind edit, at top level, in a loop body and on an activity with an error handler, andalter … replaceby one activity of the same kind does the same. Several adjacent activities each changed in their own place are each edited so; before, the run was replaced as a whole.execnow tells the two outcomes apart:spliced: 1 edited in placefor a node that kept its$ID(an activity, a decision's condition, a return's value),replaced with new element IDsfor one that did not. - The error handlers of two consecutive activities no longer share a row (ako#1768, #1672) — without
@positiona custom error handler is a row 130 px under its activity, running right, and the main line carries on one spacing after the activity however long that row is. When the next activity had a handler too, its row started at its own x, inside the first: two REST calls with three-element handlers stored the first handler's end event and the second handler's first activity both at 680;330. Neither check saw it —layout flows --dry-runre-derives with the same builder and called the flow already laid out, and MPR008 did not compare end events. A handler's row now occupies the lane under the main line the way a guard's branch already did, so whatever reaches down into that lane — the next activity with a handler, a decision, a loop — waits for it to clear, and a plain activity does not. The reported flow keeps$First, its row and$Bodywhere they were and places$Secondat 790;200, its row at 790..1110;330. The measurer counts the row too, so a loop or a branch holding handler rows is sized to them: a loop whose last handler row reached past its last activity was built 110 px wider than it was measured. Measured on 182 flows built from the02*and06doctype examples: 2 move — each an IF that followed a handler row lying under its split — and none gains an overlap;mx check0 errors on 11.13.0 before and after. - A
@positionon a later statement no longer moves the statements before it onto it (ako#1768, #1672) —declare $A String = $Url; @position(840, 200) declare $B String = $A;stored both declares at 840;200, and MPR008 reported the overlap. The start event is placed one spacing left of the first statement when that statement carries@position, but the builder took the first statement that had one, wherever it was, and the unplaced statements before it follow the start. Only the first statement moves the start now, asalter's patch and the syntax help already assumed: the flow above starts at 200;200 with$Aat 360;200 and$Bat 840;200. The syntax help and the language reference now say what happens to the statements before a placed one. - MPR008 reports an activity drawn on an event (ako#1768, #1672) — the overlap rule compared activities, loops, decisions and merges only, so an error handler's activity lying on another handler's end event at 680;330 passed, and with one more statement in that handler it reported one of the two overlaps, the one that happened to be activity on activity. Start, end, error, break and continue events and type splits are compared too, each with its stored size (an event that stores none is taken as Studio Pro's 20×20, not as an activity). On the 292 flows of the Studio Pro-authored PedApp and ako/TestApp fixtures, and on 182 flows built from the
02*and06doctype examples, the wider rule adds no finding. - A find in a loop an
alter microflowwrites is stored as a find by attribute, not as a find by an invalid expression (ako#1769, #1673) —alter microflow … { replace loop … with begin … end; }whose loop body held$Line = find $Lines by Code = $Lookup/Code;, with$Linesretrieved over an association before the loop, storedMicroflows$FindByExpressionwith the bare textCode = $Lookup/Code:check --referencesandexecreported nothing,describeprintedfind $Lines where …, and mx check failed CE0117 "Error(s) in expression."create microflowstores the same find asMicroflows$FindonMyModule.OrderLine.Code. Two causes. The guard that refuses a member a spliced fragment cannot qualify (ako#891) applied on the fragment's main line only, not in a loop, while loop or error handler inside it, and so did not coverreplace body of loopeither: there any find, filter, sort, aggregate or change member was written bare. And the fragment did not know what a stored retrieve over an association holds, nor a stored loop's iterator. Both are now typed ascreate microflowtypes them: from the association's TO end a retrieve yields the list of its FROM entity, from the FROM end the one TO object. So the reported alter writesMicroflows$Find, and what still cannot be typed (a self-reference, a list operation's output) is refused with nothing written, wherever the statement sits. Measured on Mendix 11.13.0: CE0117 before;Microflows$FindonMyModule.OrderLine.Code, mx check 0 errors, and describe → exec "Unchanged" after. - A navigation profile's application title and icon can be set and are described (ako#1756, #1664) — the title (Studio Pro's Application title,
Mendixin a new project) is what the runtime puts in every browser tab asMendix - <page title>, and it had no MDL form:create or modify navigation Responsive app title 'EWO' …failed with "extraneous input 'app'",describe navigationprinted neither it nor the Application icon, andcreate or modify translations … for en_USrefuses the source language, so every generated app kept "Mendix" in the tab.create or modify navigationnow takesapp title '<text>'andapp icon <Module.Collection.Image>(app icon noneclears it), in any order with the other clauses;appandiconstay usable as names. The title is written as the project default language's item, the title's other languages kept; the icon is resolved like any image reference, bycheck --referencesand before exec writes; an omitted clause keeps the stored value; describe prints both. A native profile has neither, so both are refused there. - A test whose earlier
@expectfails is no longer reported PASS on the after-startup runner (ako#1753) — every Docker run and--local --legacy-runnerlogged a verdict line per assertion, and the result was taken from the last one: a failing first assertion followed by a passing second reported PASS, with the failure message erased, andmxcli testexited 0. A failure now sticks, and the test reports the first one, plus how many more failed. The endpoint runner (--local,--attach,--watch) was not affected. - Two tests that assign the same variable with a lower-case
callorcreaterun on the after-startup runner (found with ako#1753) — that runner compiles every test into one microflow and renames each test's variables, but it recognised only an upper-caseCALLorCREATE.$r = call microflow …, the spelling mdl 1 andfmtwrite, was left as it was, so two tests assigning$rdeclared it twice and injection failed with MDL063 (CE0111 from mxbuild). 8 of the 16 test files inmdl-examples/hit this under Docker or--legacy-runner. A variable first assigned byretrieve,declareor a list operation was not renamed until ako#1775 (next entry). - Two tests that define the same variable with
retrieve,declare, a list operation or any other activity run on the after-startup runner (ako#1775) — that runner joins every test into one microflow and renames each test's variables, but which ones it renamed came from a pattern that recognised only$x = call …and$x = create …, in any case. A variable defined byretrieve,declare, a list operation or aggregate,send rest request,execute database queryor a loop iterator kept its name, so two tests defining it declared it twice and injection failed with MDL063 or MDL052 (CE0111 "Duplicate variable name" from mxbuild);setup-annotation.test.mdland the #1103 example still did, under Docker or--legacy-runner. The names now come from the parsed test body through the definition MDL063 itself counts, including those nested in anifbranch, a loop or an error handler. The endpoint runner (--local) gives each test its own microflow and was never affected. execnames every file it writes beside the model (ako#1618, #1634) —create java action … as $$ … $$stores the action in the model and writes its body tojavasource/<module>/actions/<Name>.java(a JavaScript action's tojavascriptsource/), butexecprinted only "Created java action: …", so a workflow that commits the model (.mprandmprcontents/) left the body behind and a clone got an action with no logic. Each file written, moved (rename java action) or removed (drop java action,drop javascript action, the source foldersdrop moduledeletes) is now named on its own line as a project-relative path, e.g.Wrote javasource/probe/actions/JA_Hello.java (Java action body; commit it with the model), and a run that changed any ends withFiles changed outside the model: N (javasource/, …). Stage them with the .mpr.A rewrite that leaves a file's content as it was does not touch it and is not reported.create published odata serviceon Mendix 9 and 10.0–10.3 is refused up front, naming the real reason (ako#1163) — it was refused at write time for "ODataPublish$PublishedODataService2.IncludeMetadataByDefault (Mendix 10.8.0+)". That property was not the problem: the whole document mxcli writes is a 10.4 type, and Mendix 9.24 cannot load a project that holds one. Before 10.4 a published OData service is a different document that mxcli does not write.check -pandexecnow report MDL-VERSION01 before writing anything.- A page passing
$currentObjectto a microflow or nanoflow is written on Mendix 9 and on 10.0–10.9 (ako#1163) —call microflow M.F(P = $currentObject)on a button or a data grid column was refused with "cannot store Forms$MicroflowParameterMapping.Expression (Mendix 10.10.0+)". An argument held as an expression arrived in 10.10. Before it, Studio Pro stores no argument for the enclosing object and infers it. Without the refusal, 9.24 could not even load the page, because the mapping had noVariable. Below 10.10 that argument is now left out, and a page parameter argument is stored as before. Any other expression argument is refused, naming the parameter. - A constant override in a configuration is written on Mendix 9 and on 10.0–10.8 (ako#1163) —
alter settings constant @M.C value '…' in configuration 'Default'was refused with "cannot store Settings$ConstantValue.SharedOrPrivateValue (Mendix 10.9.0+)". Before 10.9 an override's value is a flatValuestring; Studio Pro 9.24 does not know the nested form and empties the override on load. A new override is now written flat there, and an existing one is updated in its own shape. A private value has no form before 10.9 and is refused, naming the constant. - A workflow written to Mendix 9.24 has Studio Pro's property set (ako#1163) — its two state-change event handlers (
WorkflowOnStateChangeEvent,UsertaskOnStateChangeEvent, removed in 11.0) were completed only from 10.24, where they were measured.mx convert9.24.30 adds both as well, and Mendix's merge engine refuses to compare documents whose property names differ (#1373). - Workflows are written on Mendix 9 and on 10.0–10.20 (ako#1163) — every workflow was refused with "cannot store Workflows$Workflow.PersistentId (Mendix 10.21.0+)". Workflows exist from 9.0, but the persistent ID on a workflow, its activities, outcomes and boundary events arrived in 10.21. The activities' and outcomes' IDs were never refused, and
mx convert9.24 stripped them. mxcli mints these IDs itself, so below 10.21 it no longer writes them, forcreate,create or modifyand the activitiesalter workflowinserts. - A workflow with a
parallel splitno longer makes a Mendix 9 or 10.0–10.20 project unloadable (ako#1163) —execreported success, thenmx checkand Studio Pro could not load the project at all: "TypeCacheUnknownTypeException: The type cache does not contain a type with qualified name Workflows$EndOfParallelSplitPathActivity". mxcli ends every path with that marker, because from 10.21 the workflow engine runs a path only up to it, but the type itself arrived in 10.21. Before 10.21 Studio Pro stores a path as its activities and nothing more (measured on a Studio Pro 9.4 app). Below 10.21 the marker is no longer written, forcreate,create or modifyand a pathalter workflowinserts. Measured on 9.24.30 and 10.12.19: 0 errors. On 9.24,describe→execreports the workflow unchanged. 10.21 and later are unchanged. - Aggregates in microflows are written on Mendix 9 (ako#1163) — every
count,sum,average,minimumandmaximumon a 9.x project was refused with "cannot store Microflows$AggregateAction.AggregateFunction (Mendix 10.0.0+)". The version data had the aggregate's function introduced in 10.0, which belongs to the foldreduceadded. Studio Pro 9.24 stores it on every aggregate. An aggregate over an expression,reduce,allandanyare Mendix 10.0 and are still refused below it, now naming the fold. - Pluggable widgets keep the
Typeof their return types on Mendix 9.0–9.19 (ako#1163) — the version data mxcli vendors from the Model SDK had a return type'sTypeintroduced in 9.20. That version belongs toAssignableTo, which the data left out. A widget schema written to a 9.0–9.19 project therefore lost theTypeof every return type and kept anAssignableTothat version does not have. A return type that reached the property floor was refused with "cannot store CustomWidgets$WidgetReturnType.Type (Mendix 9.20.0+)". Studio Pro 9.1 and 9.4 storeTypeon every return type and noAssignableTo. The same mistake gave a group box's caption the 8.10 version of its header mode. That row changed nothing mxcli writes, because the caption is stored under another name and mxcli supports no version that old. - Pages on Mendix 9.24 and 10.x are read and written in the version's own shape (ako#1209) — several page properties are stored differently below a version: a design property's value before 10.2, a data view's page parameter before 10.0, its editability before 10.7, and a text box's placeholder before 10.11.
describeread only the newer form, so on 9.24 a describe → exec round trip removed every design property and placeholder. Writing any page with a data view or a design property was refused, andalter stylingon a stored design property reported success and changed nothing. Every write now converts to the project's form, anddescribereads both. What the older form cannot hold is refused, naming the widget: a Spacing or colour design property, conditional editability, a placeholder with parameters. - A text box's
KeyboardTypesurvives describe → exec (ako#1209) — the keyboard a native app opens had no MDL spelling and was written asDefault, so a rewrite reset it.textbox t (Attribute: Email, KeyboardType: EmailAddress)(Default,NumberPad,DecimalPad,EmailAddress,PhonePad,URL); an unknown value is MDL-WIDGET18. - A button's workflow action survives a rewrite (ako#832) —
describeprinted no action for Show user task page, Show workflow admin page or Call workflow, so re-executing a page turned them into no action (on ako/TestApp's TaskInbox and TaskDashboard, 2 of 6 user-task buttons each). They are nowopen user task [with (AssignOnOpen, OpenWhenAssigned)],open workflow with (DefaultPage: M.Page)andcall workflow M.WF [with (…)].complete tasktakeswith (ClosePage, Commit)instead of always writing both true.open workflowwithout a page is CE1834 and is refused. - Workflows written to Mendix below 11.3 load and pass
mx check(ako#1754) — every workflow had a stored start and end activity. On 10.24 and 11.0 the project no longer loaded (TypeCacheUnknownTypeException … StartWorkflowActivity). On 11.1 and 11.2,mx checkreported CE6671 and CE6689. Below 11.1, activities also carried layout keys those versions do not declare. The main flow's start and end are now implicit below 11.3, and the header annotation is the workflow's own note. - A pluggable widget's enumeration setting is written as the key the widget declares (ako#854) —
gallery g (…, onClickTrigger: Double)storedDouble, and the Gallery compares its trigger withsingleanddoubleexactly, so the row action never ran on a click whilemx checkreported 0 errors; a data grid'spagination: 'Buttons'was the same. A key in another case is now stored as the key, under both language versions, bycreate pageandalter page … setalike. A value the widget declares no key for (onClickTrigger: triple) is refused undermdl 1;as MDL-WIDGET08, naming the keys, andcheck -preports it. Migrating a script: without the header it is still written as given, and warns MDL-V1-WIDGETENUM. alter page … set (Action: …) on <gallery>writes the row click, and an ALTER that leaves a gallery's row click ambiguous is MDL-WIDGET36 (ako#854) —Action:reached the setter for a built-in widget's click property, which a pluggable widget does not have, so it was refused ("has no on-click action") whileset ('onClick': …)wrote the same slot.Action:andonClick:now reach a pluggable widget's click slot (a gallery's or data grid'sonClick). And no ALTER spelling applied MDL-WIDGET36, so a row click on a single-click selection was written andmx checkfailed the page ("The item click action is ambiguous"); the gallery is now judged as the SET leaves it — refused undermdl 1;, written with the MDL-V1-GALLERYCLICK warning under mdl 0, ascreate pagedoes.- A data grid filter's
OnChange:, a barcode scanner'sonDetect:and a combo box'sonEnterEvent:/onLeaveEvent:/onChangeFilterInputEvent:are written and described (ako#854) — these widgets' built-in definitions had no mapping for those action slots, so the action was refused undermdl 1;(MDL-WIDGET37 / MDL-WIDGET06) and dropped with a warning under mdl 0, anddescribeprinted no filter action — a Studio Pro-authored one survived a rewrite (the per-property patch of ako#832 kept it) but could not be restated, retargeted or removed. A filter's action isOnChange:on all four filters; the other slots are named by their own key, in every combo box mode. - Describe → exec keeps an input widget's "On enter" and "On leave" actions, and MDL can write them as
OnEnter:/OnLeave:(ako#1743) — the focus-in and focus-out actions every input stores (OnEnterAction/OnLeaveActionon a text box, text area, date picker, check box, radio buttons and drop-down) had no MDL property,describe pagenever read them, and the writer hard-coded an empty action into both. Re-executing the description of a Studio Pro page deleted every one: on 11.13.0 a page with seven of them came back fromdescribewith none, exec reported "Replaced page", and mx check still reported 0 errors.OnEnter:andOnLeave:take the action formsOnChange:takes (the stored names are accepted as the same properties),describe pageprints them, and describe → exec now reports "Unchanged page". "On enter" is focus entering the widget; the Enter key is a text box'sOnEnterKeyPress:. - A text box's "On enter key press" action has an MDL property,
OnEnterKeyPress:, and survives describe → exec (ako#1743, #1662) — every spelling of it (OnEnterKeyPress:,OnEnterKeyPressAction:,OnEnterKey:) was reported as a property mxcli does not write on a textbox and dropped,describeprinted nothing and mx check passed, so a search box that searches on Enter could not be generated; and the writer hard-coded an empty action intoForms$TextBox.OnEnterKeyPressAction, so re-executing the description of a Studio Pro text box deleted its enter-key action.OnEnterKeyPress:now takes the action formsOnChange:takes, the stored name is accepted as the same property, anddescribe pageprints it back. A text area has no such slot in Mendix's metamodel (onlyForms$TextBoxdoes), so there the key is refused with that reason instead of being written nowhere. checkrefuses a combo box's custom-content type without the content (ako#1744, #1663) —optionsSourceAssociationCustomContentType: 'yes'(or'listItem', or the database mode'soptionsSourceDatabaseCustomContentType) written with no content block passedcheckandexec, and mx check reported CE0642 "Property 'Custom content' is required." at Widgets container 'Custom content' of combo box. It is now MDL-WIDGET53, andexecrefuses it too, with no project needed. A content block under the type'no'is refused the same way — the editor hides the content then, and mx check reported CE0463 — and a block with the type left out writes'yes'.describe pagenames content stored under'no'in its NOT SHOWN note rather than printing a block that would re-execute as shown. Measured on Mendix 11.13.0 with Combo box 2.5.0: the type alone, CE0642 before and refused now; a block with the type left at'no'CE0463, with the type left out (written'yes') 0 errors,mx update-widgetschanging nothing.- A combo box's custom content can be written, and
describe pageprints it back (ako#1744, #1663) — custom content is how a combo box shows more than one attribute per option, andmxcli widget describe comboboxlisted it as awidgetsproperty, butcombobox cbPerson (…) { optionssourceassociationcustomcontent { dynamictext … } }was refused bycheck -pwith MDL-WIDGET26 "optionssourceassociationcustomcontentis not a container ofcombobox, which declares no containers", andexecfailed on it. Each option-source mode now has its slot:optionssourceassociationcustomcontentin association mode,optionssourcedatabasecustomcontentin database mode, its widgets bound to the option entity. The other mode's block, or any block on an enumeration combo box, is refused (MDL-WIDGET30) naming the slot the mode does have, and the slot's key written as a value is MDL-WIDGET27.describe pageprints the mode's content as that block instead of a NOT SHOWN note, so describe → exec reports "Unchanged page", and acreate or modifythat changes the combo box restates the content instead of being refused (ako#1648 still refuses for content outside the described mode).widget describemarks the two slots "association mode only" / "database mode only". Measured on Mendix 11.13.0 with Combo box 2.5.0: the reported page and a database-mode combo box with content,mxcli docker check --no-update-widgets0 errors;mx update-widgetschanges nothing in the written page; describe → exec "Unchanged page"; the combo box's label changed in the description → "Replaced page", content kept, 0 errors. A static-mode combo box's per-value content (staticDataSourceCustomContent) is not covered: the static values themselves have no MDL spelling yet. check -p --referencestypes the result ofcall microflow, so a Hidden attribute read on it is reported (CE1406) (ako#1701, #1654) —$Request = call microflow AddOn.Request_GetFirst(); declare $Secret String = $Request/Secret;in an app module passedcheckandexecwhileSecretwas a Hidden attribute of a Protected (add-on) module, and mxbuild refused it:[CE1406] "Create variable activity 'Create String variable' is not allowed to use attribute 'AddOn.Request.Secret' because app modules cannot reference hidden elements in add-on modules."The same read through a parameter was reported. The variable-typing walk the--referencesmember checks share typed parameters,create,retrieveand loop iterators but not a call's output; it now takes the callee's object or list return type — the script's own definition of the callee first (acreate or modifychanges what exec writes), else the stored microflow. The member-existence check gains the same reach: a CHANGE on a call result naming a member the returned entity does not have now reports CE1613 instead of passing. Measured on Mendix 11.13.0: a declare, an end event and a change on the result, and a change on a loop over a returned list, each refused on the Hidden attribute; the Usable one beside it is 0 errors.check -p --referencesreports CE1406 for a retrieve, create or create list of a Hidden entity of a Protected module (ako#1699, #1652) — a flow in an app module that ranretrieve $l from AddOn.Internal,$o = create AddOn.Internalor$l = create list of AddOn.Internalon a Hidden entity of a Protected (add-on) module passedcheckandexec, and mxbuild refused it:[CE1406] "Retrieve object(s) activity 'Retrieve list of Internal from database' is not allowed to use entity 'AddOn.Internal' because app modules cannot reference hidden elements in add-on modules."(likewise "Create object activity", "Create list activity"). The check judged an entity only as a parameter or return type; it now judges the entity these three activities name, in microflows and nanoflows, andexecrefuses the script before writing it. Measured on Mendix 11.13.0: each shape refused against a Hidden entity, 0 errors against a Usable one and inside the add-on; an association retrieve that reaches a Hidden entity over a Usable association names only the association and is not refused.- A pluggable widget's text-template parameter across an association builds, and describes so it re-executes (#1494) —
fieldset fs (legend: '{1}', legendParams: ({1} = M.Parent_Child/Label))passedcheckandexecand failed the build with[CE1365] "Attribute 'M.Child.Label' is not an attribute of entity 'M.Parent'.": the parameter was written with its attribute but without the association hop, so mxbuild read the attribute against the widget's own entity. The same writer serves an object-list item's template (an Accordion group'sheaderText) and a Data grid 2 column's dynamic text, and all three failed; on Mendix 11.12.4 they now build with 0 errors.describe pageprinted such a parameter as the bare attribute ({1} = Label), which re-executed into CE1613 "The selected attribute 'M.Parent.Label' no longer exists"; it now printsM.Parent_Child/Label. The companion report, an expression parameter ({1} = if 1 = 1 then 'A' else 'B') stored as an attribute name (#1495), was fixed in v0.25.0 (#823) and is now pinned by a test. alter entity … add event handleradds a second handler for the same event (#1540) —add event handler on before commit call M.Second($currentObject)failed with "event handler already exists for Before Commit" when the entity already had one, though Studio Pro allows several handlers for one event andcreate or modify entitywith twoon before commitclauses stores both (measured on 11.12.4: two Before Commit handlers are 0 errors, a void-returning one is CE7247, so the check does look at them). A handler is now identified by its moment, event and microflow: another microflow adds a second handler, the same microflow again is still a duplicate. The same key had madeadd event handler if not exists … call M.Newskip — reporting "already exists" — whenever any handler for the event existed, anddrop event handler on before commitremove whichever handler was stored first.drop event handlernow takescall M.Mfto say which one; without it, a drop that matches several handlers is refused and names them.- A bare
create or modify module role M.R;keeps the role's description (ako#1218) — the "make sure this role exists" statement reportedModified module role: M.Rand erased the stored description: a statement withoutdescriptionwas written as an empty one. An omitteddescriptionnow keeps what is stored, as an omitted user role property already did, and the run reportsUnchanged;description ''clears it. Grants were never affected, anddescribe→execwas not, sincedescribeprints the description. Measured on Mendix 11.13.0:mx checkis 0 errors with and without the fault, so only the stored description showed it. checkrefuses whatmx checkwould, before anything is written — each of these passedcheck -pandexecand failed afterwards:- a widget property the widget does not take, such as
Caption:on a text box (written with no label) orVisible:on a snippet call (ako#1698); MDL-WIDGET07 judged every widget against the union of all widgets' properties; - a member named like one on its generalization chain, CE0069 (ako#1645); a find, filter, sort or aggregate by a member the entity lacks, and an aggregate by an inherited attribute, CE1613 (ako#1646);
$Var/memberfor a member the entity lacks,idincluded, CE0117 (ako#1697); - a page parameter named
Context, CE7247 (ako#1651); an XPath[%UserRole_X%]naming no user role, a CE1613 that also hides every CE0161 elsewhere; a SET that leaves a date picker Custom with no pattern, CE0493 (#977); - a Java action parameter or return type it cannot store: a
StringTemplateparameter written as a String, an unreturnable type written as Boolean (MDL-JA03), aStringTemplateon a JavaScript action (MDL-JSA01), a bare enumeration stored as an entity (ako#935), and a text-template or document argument tocall java actionbound as text, CE0115 (ako#1451).
- a widget property the widget does not take, such as
- Statements write what they say —
retrieve $C from $O/Ord_Custwith the association's short name is stored with its module, not as.Ord_Cust(ako#1690);where Total > @Shop.C_Limitparses, and a constant in an XPath constraint is no longer dropped on write or describe (ako#1685);log … with ({1} = …)andsend emailover a variable send its value, not the text$Msg, andshow messageandvalidation feedbackno longer shift the stated parameters by one (ako#1683);- an
ifwithoutelseinside an error handler keeps its false case, CE0079 (ako#1455); a change next to afind … wherewith a bare member no longer reads the find as changed too (ako#856); - a view entity accepts
STRING_AGGbeside GROUP BY (ako#1650), and types a CASE column from its first branch, so the declaration MDL031 asked for no longer fails CE6770; - a routine header without parentheses is one error at the mistake, not three after it.
- Renames, moves and drops update what refers to them —
rename constantand a cross-modulemove constantrewrite@Module.Constin expressions, andrename enumerationa value inside a longer expression (ako#1671);move enumerationrewrites parameters, variables and return types, not only attributes (ako#1674);rename attributeno longer rewrites every unrelated XPath constraint with a line break in it, 147 units in 21 modules on one project (ako#1506);drop entityremoves the association's member access from the entity at the other end (ako#1449); and moving an OWNER Both association's TO end reconciles the entity access of both modules, CE0066 (ako#819). - More pages survive describe → exec unchanged — a read-only data view stays read-only, and
alter page … set (Editable: …)accepts a 10.7+ data view; text box, text area, date picker and radio buttons keepReadOnlyStyle(#977); a microflow data source keeps its FormValidations (#1729); a stored DisabledDuringExecution false is kept on pluggable widgets and layouts (#549); texts keep their stored language order, and a multi-placeholder page its placeholder order (#1704); a dynamic text'scustomDateFormatwith a quoted literal is escaped both ways (#977); a button passing a grid's or combo box's selection keeps that argument, where it gave CE1571; a pluggable widget's text-template parameter across an association describes as the path; a data grid filter's Placeholder and Adjustable are written bycreate page(ako#1652); and an action with no target yet is described as a note instead of output that does not parse (#1728).describe fragmentprints flow arguments and whole actions. diff-localshows every change (ako#1512) — a settings change, a grant on an entity or domain model, and any unit without an MDL renderer now print a hunk or the changed fields instead of "(no changes)";--ref a...bcompares against the merge base instead of reading every unit at.b; a moved.mxunitis one unit deleted and one added; and it runs from outside the project's git repository.- Lint and
refs— a published OData service's read and authentication microflows are references, sorefs,impactand QUAL004 no longer call them dead (ako#1639); neither is a microflow started only from the navigation (ako#1484); and a finding's location no longer repeats the module (at M.M.NAV_Home). - The local dev loop —
run --localno longer hangs for minutes, silently, behind an idle Gradle daemon from an earlier run (ako#1340); a session-start hook no longer deletes a live run'srun-local.json, andrun statusgives the stop reason, the trial licence's run-time limit included (ako#1542);--ensure-dbno longer provisions an empty cluster on the port while the system cluster is down, which booted the app healthy against no data (ako#866);mxcli test --localbuilds when the app's after-startup microflow applies entity access, CE0114 (ako#1654);import … linklinks, where it reported success and linked nothing on every Mendix version (ako#1454);playwright checkwaits for a data source to render before its verdict (ako#845), fails an unknown/p/URL instead of passing the home page (ako#998), signs in on each host it checks (ako#1216), reports a page the role may not open as access denied instead of signing in again, and no longer waits out--waiton the sign-in form.
- Smaller fixes —
show versionreports MPR v1 for an MPR v1 project (ako#1553); a catalog query no longer stripsCatalog.inside a string literal, so a module named Catalog can be filtered on (ako#1450); a user task's group XPath targeting is read back instead of dropped, and its targeting XPath is checked against the user entity; an interrupting boundary path ends with an End, as Studio Pro writes it.
Full Changelog: v0.28.0...v0.29.0