lock workflow all; and unlock workflow all; parse, pass mxcli check, and execute successfully — then mxbuild rejects the result. The MDL form appears to have no valid representation in the model at all, so this is a question about what the syntax should mean rather than a defect with one obvious fix.
Found while adding reader coverage for the workflow call actions, which deliberately left this alone.
Reproduction
create module W;
create microflow W.MF_LockAll ()
begin
lock workflow all;
unlock workflow all;
end;
$ mxcli exec t.mdl -p AppWF.mpr
Created microflow: W.MF_LockAll
$ mx check -p AppWF.mpr
[error] [CE1825] "The 'Workflow' property is required." at Lock workflow activity 'Lock workflow'
[error] [CE1825] "The 'Workflow' property is required." at Unlock workflow activity 'Unlock workflow'
The app contains: 2 errors.
Mendix 11.13.0. Both engines — identical output with --engine legacy, so this is not modelsdk-specific.
Control
The variable form is fine, which isolates the failure to all:
| statement |
mx check |
lock workflow $WfDef / unlock workflow $WfDef |
0 errors |
lock workflow all / unlock workflow all |
2 errors (CE1825) |
Why the obvious fix doesn't work
The writer omits WorkflowSelection when the "all" flag is set:
// mdl/backend/modelsdk/microflow_workflow_write.go:77
addBool(g, "PauseAllWorkflows", a.PauseAllWorkflows)
if !a.PauseAllWorkflows {
addPart(g, "WorkflowSelection", workflowSelectionToGen(a.Workflow, a.WorkflowVariable))
}
(sdk/mpr/writer_microflow_workflow.go:156 has the same guard.)
I tried always emitting the selection. It still fails with CE1825 — because in the all form there is no workflow to name, so workflowSelectionToGen("", "") produces an object selection with an empty variable, which is just as unset.
What the metamodel says
From the Mendix Model SDK (mendixmodelsdk, gen/workflows.d.ts), WorkflowDefinitionSelection has exactly two concrete subclasses:
WorkflowDefinitionNameSelection — a workflow qualified name
WorkflowDefinitionObjectSelection — a WorkflowDefinition variable
There is no all-definitions variant. On LockWorkflowAction, workflow was deleted in 10.0.0, workflowSelection was introduced in 10.0.0, and pauseAllWorkflows defaults to true.
That combination suggests pauseAllWorkflows does not mean "all workflow definitions" at all — more likely "all instances of the selected definition". If so, a lock/unlock always needs a specific definition, and MDL's all keyword is expressing something the model cannot represent.
The decision to make
mdl/grammar/domains/MDLMicroflow.g4:472 currently allows:
lockWorkflowStatement
: LOCK WORKFLOW (VARIABLE | ALL) onErrorClause?
Options, roughly in order of my confidence:
- Drop the
ALL alternative. If the model cannot express it, accepting it only produces unbuildable projects. Existing scripts using it are already broken.
- Require a workflow with the flag — e.g.
lock workflow $WfDef all / lock workflow W.Approve all, mapping to a selection plus PauseAllWorkflows: true. This matches the "all instances of that definition" reading, but I have not confirmed that reading against Studio Pro.
- Refuse at author time (an MDL rule, like MDL058), keeping the grammar but rejecting before the write.
Settling between (1) and (2) needs one Studio Pro data point: create a Lock workflow activity with the "pause all" checkbox ticked and see whether it still stores a WorkflowSelection. That would confirm what the flag means and whether option 2 is real.
Scope note
Whatever is chosen, it should also cover sdk/mpr (legacy), since both engines emit the same shape.
Generated by Claude Code
lock workflow all;andunlock workflow all;parse, passmxcli check, and execute successfully — then mxbuild rejects the result. The MDL form appears to have no valid representation in the model at all, so this is a question about what the syntax should mean rather than a defect with one obvious fix.Found while adding reader coverage for the workflow call actions, which deliberately left this alone.
Reproduction
Mendix 11.13.0. Both engines — identical output with
--engine legacy, so this is not modelsdk-specific.Control
The variable form is fine, which isolates the failure to
all:mx checklock workflow $WfDef/unlock workflow $WfDeflock workflow all/unlock workflow allWhy the obvious fix doesn't work
The writer omits
WorkflowSelectionwhen the "all" flag is set:(
sdk/mpr/writer_microflow_workflow.go:156has the same guard.)I tried always emitting the selection. It still fails with CE1825 — because in the
allform there is no workflow to name, soworkflowSelectionToGen("", "")produces an object selection with an empty variable, which is just as unset.What the metamodel says
From the Mendix Model SDK (
mendixmodelsdk,gen/workflows.d.ts),WorkflowDefinitionSelectionhas exactly two concrete subclasses:WorkflowDefinitionNameSelection— a workflow qualified nameWorkflowDefinitionObjectSelection— aWorkflowDefinitionvariableThere is no all-definitions variant. On
LockWorkflowAction,workflowwas deleted in 10.0.0,workflowSelectionwas introduced in 10.0.0, andpauseAllWorkflowsdefaults totrue.That combination suggests
pauseAllWorkflowsdoes not mean "all workflow definitions" at all — more likely "all instances of the selected definition". If so, a lock/unlock always needs a specific definition, and MDL'sallkeyword is expressing something the model cannot represent.The decision to make
mdl/grammar/domains/MDLMicroflow.g4:472currently allows:Options, roughly in order of my confidence:
ALLalternative. If the model cannot express it, accepting it only produces unbuildable projects. Existing scripts using it are already broken.lock workflow $WfDef all/lock workflow W.Approve all, mapping to a selection plusPauseAllWorkflows: true. This matches the "all instances of that definition" reading, but I have not confirmed that reading against Studio Pro.Settling between (1) and (2) needs one Studio Pro data point: create a Lock workflow activity with the "pause all" checkbox ticked and see whether it still stores a
WorkflowSelection. That would confirm what the flag means and whether option 2 is real.Scope note
Whatever is chosen, it should also cover
sdk/mpr(legacy), since both engines emit the same shape.Generated by Claude Code