Skip to content

fix(check): refuse an operator inside an XPath function argument (MDL091) - #1012

Merged
ako merged 4 commits into
mainfrom
fix/1326-xpath-function-argument-operator
Oct 7, 2026
Merged

ako merged 4 commits into
mainfrom
fix/1326-xpath-function-argument-operator

Conversation

@ako

@ako ako commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Fixes mendixlabs#1326.

Symptom (verbatim from the issue)

A concatenation inside an XPath function argument of a retrieve … where passes check --references and exec, for example starts-with(Name, 'MS-' + $Key).

…and mx check then reports CE0161 "Error(s) in XPath constraint."

Cause

MDL091 only matched expression-only function names (startsWith, endsWith, getKey) by regex over the rendered XPath string. It never looked at what a function's arguments are.

Fix

mdl/executor/validate_microflow.go: walk the retrieve constraint's AST and flag a function argument that is itself a + or - operation, after unwrapping parentheses and the SourceExpr wrapper. MDL091 is exec-enforced, so exec now refuses it too. The suggestion tells the user to compute the value into a variable first.

The bracketed […] form needed no change: its grammar already refuses an operator in a function argument as a parse error.

Evidence

Tests

  • TestValidateMicroflow_XPathFunctionArgumentOperator: 10 shapes, both flagged and clean.
  • TestCheckExecAgree_RetrieveConstraintFunctionArgumentOperator: check -p and exec both refuse the bad form, and both accept the two shapes the issue reports as clean.

Control. With checkXPathFunctionArgumentOperators stubbed out, both tests fail with the reported symptom:

xpath_function_operator_test.go:74: check -p must report MDL091 for the operator, reported:
xpath_function_operator_test.go:77: exec must refuse the operator with MDL091, got: <nil>

mxbuild 11.14.0, both variants. I wrote the faulty constraints with a build that had the check stubbed out, then ran mxcli docker check on that project and on a control project:

Constraint mx check
starts-with(Name, 'MS-' + $Key) CE0161
not(contains(Name, $Key + $Key)) CE0161
contains(Name, $Key - 'a') CE0161
Name = 'X-' + $Key 0 errors
year-from-dateTime(Due) = $N - 1 0 errors
starts-with(Name, $P) 0 errors

The fixed binary refuses the bad script: "Refusing to execute: 2 error(s) above. Nothing was written."

Not flagged on purpose: *, div, mod. Their only possible argument is a number, and the control contains(Name, $N) with an Integer $N is already CE0161 with no operator at all. No measurement isolates the operator, and because MDL091 blocks exec, I left out anything not shown to fail.

Also in this PR

  • Regression script mdl-examples/bug-tests/1326-xpath-function-argument-operator.fail.mdl: the bad microflow plus two clean controls.
  • A note in the xpath-constraints skill.
  • One finding appended to findings/mdl-executor.jsonl.

Checks

make build, make test, make lint, make check-mdl and make check-findings all pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_015mwKd8LDw9MRoZ8uBbbnAg


Generated by Claude Code

claude added 4 commits October 7, 2026 05:32
…091)

`retrieve … where starts-with(Name, 'MS-' + $Key)` passed `check
--references` and `exec`, then failed mx check with CE0161 "Error(s) in
XPath constraint." (mendixlabs#1326). MDL091 only matched
expression-only function names in the rendered XPath string; it never
looked at what a function's arguments are.

Walk the retrieve constraint's AST and flag a function argument that is
itself a `+` or `-` operation. MDL091 is exec-enforced, so exec now
refuses it as well. Measured on mxbuild 11.14.0 with the check stubbed
out to force the fault in:

  starts-with(Name, 'MS-' + $Key)      CE0161
  not(contains(Name, $Key + $Key))     CE0161
  contains(Name, $Key - 'a')           CE0161
  Name = 'X-' + $Key                   0 errors
  year-from-dateTime(Due) = $N - 1     0 errors
  starts-with(Name, $P)                0 errors

`*`, `div` and `mod` are not flagged: their only possible argument is
numeric, and `contains(Name, $N)` is CE0161 with no operator, so no
measurement isolates the operator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015mwKd8LDw9MRoZ8uBbbnAg
@ako
ako merged commit d658df1 into main Oct 7, 2026
29 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.

Concatenation inside an XPath function argument (starts-with(Name, 'MS-' + $Key)) passes check; mx check CE0161 (follow-up to MDL091)

2 participants