cheatsheet-errors

Quick fixes for the MDL syntax errors that come up most: undeclared variables, wrong retrieve source, list operations, expression mistakes. Use when `mxcli check` reports an error and you want the fix

SKILL.md

GitHub
<!-- skill-index: generated by scripts/skill-index.py; make check-skill-index -->

Find it fast

sed -n '<from>,<to>p' SKILL.md one section rather than reading the file; ./mxcli syntax <topic> answers how do I write this for a fraction of either.

lines section
26-78 Variable Errors
79-130 Expression Errors
131-184 Control Flow Errors
185-222 Syntax Errors
223-287 Reference Errors
288-303 Studio Pro Error Code Reference
304-315 Quick Validation Checklist
<!-- /skill-index -->

MDL Common Errors Cheatsheet

Quick fixes for common MDL syntax errors.

Variable Errors

"Variable 'X' is not declared"

Problem: Using SET on a variable that wasn't declared.

-- WRONG
if $value > 10 then
  set $IsValid = false;  -- ERROR: $IsValid not declared
end if;

Fix: Add DECLARE before SET.

-- CORRECT
declare $IsValid boolean = true;
if $value > 10 then
  set $IsValid = false;
end if;

"Selected type is not allowed" (CE0053)

Problem: Declaring an object (entity) or list variable. A declare maps to a Create Variable activity, which only accepts primitives (String/Integer/Long/Decimal/Boolean/DateTime/Enumeration). Declaring an object or list is rejected (CE0053/CE0038, plus CE7247 on any later set) — bare or initialized. The as keyword is also a parse error in mxcli. mxcli check flags an object declare as MDL043 and a list declare as MDL040.

-- WRONG: declaring an object — there is no "empty object variable" (MDL043)
declare $Product Module.Product = empty;
declare $Product as Module.Product;         -- AS is also a parse error
-- WRONG: declaring a list (MDL040)
declare $Products list of Module.Product = empty;

Fix: Objects and lists can't be declared — get them from a source that produces one.

-- object: a microflow parameter, a retrieve, a create, or a loop iterator
retrieve $Product from Module.Product where Code = $Code first;  -- retrieve
$Product = create Module.Product (Name = $Name);                   -- create
-- or: create microflow M.Save ($Product: Module.Product) ... / loop $Product in $Products ...

-- list: a parameter, a retrieve, or a create list
$Products = create list of Module.Product;   -- empty list to accumulate into
retrieve $Products from Module.Product where ...;  -- or populate from the database

Expression Errors

"Error in expression" (CE0117)

Problem 1: Using unqualified association name in XPath.

-- WRONG: Missing module qualification
set $Name = $Order/Customer/Name;

Fix: Use fully qualified association name.

-- CORRECT: Module.AssociationName
set $Name = $Order/Shop.Order_Customer/Name;

Problem 2: Using not without parentheses — Mendix requires not(expr) form.

-- WRONG: bare not rejected by Studio Pro
if not $IsActive then ...
if not contains($Name, 'demo') then ...

Fix: Always wrap the negated expression in parentheses.

-- CORRECT: not(expr)
if not($IsActive) then ...
if not(contains($Name, 'demo')) then ...

mxcli enforces this at parse time — not expr without parens is a syntax error.

"Type mismatch" in enum comparison

Problem: Comparing enumeration with string literal.

-- WRONG: String literal instead of enum value
if $task/status = 'Completed' then

Fix: Use qualified enumeration value.

-- CORRECT: Module.Enumeration.Value
if $task/status = Module.TaskStatus.Completed then

Control Flow Errors

"Activity cannot be the last object" (CE0105)

Problem: Missing RETURN statement.

-- WRONG: No RETURN
begin
  declare $Result boolean = true;
  log info 'Done';
  -- Missing RETURN!
end;

Fix: Add RETURN statement.

-- CORRECT
begin
  declare $Result boolean = true;
  log info 'Done';
  return $Result;
end;

"Action activity is unreachable" (CE0104), or CE0709 / CE0105

Problem: A statement that can never run — after return, raise error, break, continue or join in the same block, after an if/else that returns on both sides, or after a while true with no break. The code depends on where the dead statement hangs: right after a return inside an if it is CE0709 "Sequence flow is not accepted by origin or destination", after a loop or an if/else it is CE0104 (plus CE0105 if it is the last statement). mxcli check refuses all of them as MDL-FLOW05.

-- WRONG: Code after RETURN
if $value < 0 then
  return false;
  log info 'Negative';  -- Unreachable!
end if;

Fix: Move code before RETURN.

-- CORRECT
if $value < 0 then
  log info 'Negative';
  return false;
end if;

Syntax Errors

Division operator

-- WRONG: Using / for division
set $average = $Total / $count;

-- CORRECT: Use 'div' keyword
set $average = $Total div $count;

Missing END IF / END LOOP

-- WRONG: Missing END IF
if $value > 0 then
  set $Positive = true;
-- Missing END IF!

-- CORRECT
if $value > 0 then
  set $Positive = true;
end if;

Missing semicolons

-- WRONG: Missing semicolon
declare $count integer = 0
set $count = 1

-- CORRECT
declare $count integer = 0;
set $count = 1;

Reference Errors

"Module not found"

Problem: Using non-existent module name.

Fix: Check module exists with list modules.

"Entity not found"

Problem: Using non-existent entity name.

Fix:

  1. Check entity exists: list entities in ModuleName
  2. Use fully qualified name: Module.EntityName

"Microflow not found"

Problem: Calling non-existent microflow.

Fix:

  1. Check microflow exists: list microflows in ModuleName
  2. Use fully qualified name: Module.MicroflowName

"page not found" for a page the script creates further down (MDL-PAGE01)

Problem: A widget action targets a page created by a LATER statement in the same script. Page references resolve in statement order, and exec is not transactional — the statements before the failure are already written.

Fix:

  1. Move the create page for the target above the page that links to it.
  2. If two pages link to each other, no ordering works: create one without the linking widget, then add it with alter page ... insert.
  3. Commit before executing a large script — recovery from a partial run is git checkout -- App.mpr mprcontents/.

"not found" for anything else the script creates further down (MDL-ORDER01)

Problem: Same shape as MDL-PAGE01, for the other references the executor resolves when it writes the referring document — a flow's parameter or return type, an entity attribute's enumeration, an association endpoint, or a grant subject. check used to pass these and exec then failed partway through.

Fix: Move the create for the named document above the statement that uses it. Statements have no dependency order beyond this, so grouping entities and enumerations at the top of a script avoids it entirely.

Not every forward reference is an error. These execute fine with the definition afterwards, and are deliberately not flagged: an entity's extends generalization, call java action, retrieve ... from, and create <entity> inside a microflow body.

A call microflow/call nanoflow target created further down is resolved by plain mxcli exec, which rolls the whole run back if a statement fails, so mutually recursive flows can be written in either order (mendixlabs/mxcli#1405). exec --continue-on-error, the REPL and -c cannot roll back and refuse it ("this run cannot be rolled back"): create the callee first, or a stub of it first and create or modify it after the caller.

One case check cannot predict: if the document is created later by create or modify, exec still fails when the project does not already have it — but the script alone cannot say whether it does, so no error is reported. Run with -p for the fullest coverage.

Studio Pro Error Code Reference

Code Message Common Cause
CE0053 Selected type is not allowed Declared an object/list variable — get it from a parameter/retrieve/create/loop (MDL043 objects, MDL040 lists)
CE0104 / CE0709 Activity is unreachable / Sequence flow is not accepted Code after RETURN, BREAK, CONTINUE, JOIN, or a while true with no BREAK — check flags MDL-FLOW05
CE0105 Must end with end event Missing RETURN
CE0117 Error in expression Unqualified association path
CE0117 …on a button inside a data container The button passes the container it sits in by its widget name ($dvGate inside dvGate). That name is a variable only for containers nested below it; use $currentObject there. Same for data-source arguments, Visible:, Editable:, DynamicClasses:, and (as CE0161) a nested list's XPath where. MDL-BUTTON02
CE1571 No argument selected for parameter A microflow/nanoflow call with a parameter nothing fills — as a datasource: or an action:. Give it an argument (action: call nanoflow M.NF(P = $value)), or nest the widget in a data container of the parameter's type. check -p reports both
CE1571 …in a control bar A control bar is not row-scoped, so the grid's row does not fill it: pass the grid's selection ($dgOrders, with Selection: set) or move the widget into a column. $currentObject there is MDL-BUTTON01
CE1834 The 'Page' property is required Workflow user task without a page — check flags MDL-WF01
CE1876 Single outcome must not contain activities Single-outcome user task with a nested activity flow — check flags MDL-WF02
CE6686 Outcomes do not match the configured expression/microflow An enumeration decision or call-microflow activity missing the empty outcome ('' -> { }) or an enumeration value — check flags the missing empty one as MDL-WF06
CW0094 Variable never used Unused parameter/variable

Quick Validation Checklist

Before executing MDL:

  • No object or list is declared — objects come from a parameter/retrieve/create/loop (MDL043); lists from a parameter/retrieve/create list (MDL040)
  • All SET targets have prior DECLARE
  • Association paths are qualified: $var/Module.Assoc/attr
  • Enum comparisons use Module.Enum.Value
  • Every flow path ends with RETURN
  • Division uses div not /
  • All statements end with ;
  • IF/LOOP properly closed with END IF/END LOOP