Skip to content

fix(workflow): stop naming a jump activity after its target (mendixlabs/mxcli#1005) - #350

Merged
ako merged 3 commits into
mainfrom
fix/workflow-jump-target-validation
Aug 31, 2026
Merged

fix(workflow): stop naming a jump activity after its target (mendixlabs/mxcli#1005)#350
ako merged 3 commits into
mainfrom
fix/workflow-jump-target-validation

Conversation

@ako

@ako ako commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Fixes mendixlabs/mxcli#1005. Independent of the two describe PRs — branches off main.

buildJumpTo set the jump activity's Name to its target's name. Mendix resolves TargetActivity by name, so the jump could resolve to itself, and CE6681 ("not possible to jump to end activities or jump-to activities") then describes a different fault than the real one.

Nothing caught it first. A jump target is the only intra-document reference a workflow has — validateWorkflowStatementRefs resolves microflows, pages and entities, and never looks at activity names. So check --references passed, exec reported success, and the defect surfaced only under the native validator.

A second case, not in the report

A forward jump to a target that does exist breaks identically, because deduplication renames the second activity carrying a name:

jump's stored Name real target
backward (target first) StepB2 StepB works — the reported "valid target" row
forward (jump first) StepB StepB2 self-reference → CE6681

Straight from the control run against unfixed code:

--- FAIL: TestJumpTo_NeverTakesTheTargetsName/forward
    jump is named after its target ("StepB") — it targets itself
    target "StepB" is not the name of any activity; names present: map[StepA:true StepB2:true]

Loops jump backwards, which is why the reported table shows a valid target as safe. Fixing only the unresolved-target case would have left half the bug.

The fix, both ends

The valid-target set comes from running the real builders over the AST, not from re-deriving names here: a call microflow M.SUB_X activity is named SUB_X, and a second copy of that rule would drift into exactly the false refusals this rule exists to prevent. No project needed — every name comes from the script. Jumps are excluded from the set, since Mendix refuses a jump to a jump.

The suggestion lists the valid names, because they aren't visible in the script — which is most of why the wrong name is easy to reach, and why describe → edit → exec produces this:

jump target "callMicroflow2" does not match any activity in this workflow — Mendix
resolves a jump by activity name, so this is written as a jump to itself and the build
fails with CE6681 (...)
  → Valid targets in this workflow: SUB_CheckPackageAvailability. A `call microflow`
    activity is named after the microflow it calls.

Tests

Eight, verified against unfixed code (three fail, including the forward case above). Controls that matter: a valid jump in both directions must not be flagged (otherwise the rule could pass by refusing everything), a target nested in an outcome flow must resolve (otherwise every jump into a branch is refused), and two jumps in one workflow must get distinct names.

That last one earned its place immediately — a careless bulk edit left if jumpPass { if !jumpPass { in the dedup, silently disabling all jump renaming. Only the uniqueness test caught it; CE0495 would have been the next bug report.

🤖 Generated with Claude Code

ako and others added 3 commits August 31, 2026 19:01
buildJumpTo set the jump's Name to its target's name. Mendix resolves
TargetActivity BY NAME, so the jump could resolve to itself; the build
then fails CE6681 ("not possible to jump to end activities or jump-to
activities"), which describes a different fault than the real one.

Nothing caught it first. A jump target is the only INTRA-document
reference a workflow has: validateWorkflowStatementRefs resolves
microflows, pages and entities, and never looks at activity names. So
`check --references` passed, `exec` reported success, and the defect
surfaced only under the native validator.

The reported trigger is an unresolved target. There is a second case,
not in the report: a FORWARD jump to a target that DOES exist breaks the
same way, because deduplication renames the second activity carrying a
name. Measured:

  backward (target first)  jump -> StepB2, target keeps StepB   worked
  forward  (jump first)    jump KEEPS StepB, target -> StepB2   broke

which is why loops looked fine and the reported table says a valid
target is safe. Fixing only the unresolved case would have left half the
bug in place.

Both ends are fixed. A jump is named JumpTo (deduped: JumpTo, JumpTo2,
...) so it can never carry a target's name, and deduplication now runs
in two passes with jumps LAST, so a jump never claims a name a real
activity wanted whatever it is called.

MDL-WF05 refuses an unresolved target at check time and, via the same
function, in execCreateWorkflow — exec is reachable without check (the
mendixlabs#833 lesson). The valid-target set comes from running the real builders
over the AST rather than re-deriving names, because a `call microflow
M.SUB_X` activity is named SUB_X and a second copy of that rule would
drift into false refusals. The suggestion lists the valid names: they
are not visible in the script, which is most of why the wrong one is
easy to reach.

Reported as mendixlabs#1005.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ako
ako merged commit 7560ceb into main Aug 31, 2026
16 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant