Skip to content

Commit db6ccc4

Browse files
authored
Merge pull request #1054 from ako/main
Five defects from CapTrackV3: two properties written wrong in silence, and a sort path that stopped the project loading at all
2 parents e6c103c + 7658bbe commit db6ccc4

23 files changed

Lines changed: 1274 additions & 36 deletions

‎.claude/skills/fix-issue/findings/mdl-executor.jsonl‎

Lines changed: 5 additions & 0 deletions
Large diffs are not rendered by default.

‎mdl-examples/bug-tests/308-commit-on-error-rollback-roundtrip.mdl‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,19 @@ begin
4343
end;
4444
/
4545

46-
-- Negative control: explicit `on error continue` must survive equally.
47-
create microflow BugTest308.MF_CommitContinue (
48-
$Item: BugTest308.Item
49-
)
50-
begin
51-
commit $Item on error continue;
52-
end;
53-
/
46+
-- The `on error continue` case that used to sit here has been REMOVED, because
47+
-- it asserted something that does not build. Measured on 11.14.0: the statement
48+
-- stores `Continue` exactly as this file expected, and mxbuild then rejects it —
49+
--
50+
-- commit $Item on error continue;
51+
-- mx check -> [CE6035] "Error handling type is not supported"
52+
-- at Commit object(s) activity 'Commit 'Item''
53+
--
54+
-- The example was written for round-trip fidelity and its Usage block never ran
55+
-- `mx check`, so a describe -> exec -> describe fixpoint was mistaken for a valid
56+
-- model. `mxcli check` now reports it as MDL076, which is why this file failed
57+
-- `make check-mdl` the moment that rule landed.
58+
--
59+
-- Continue IS supported on `retrieve`, `delete` and `call microflow`, and their
60+
-- round-trip is covered by `error-handling-continue.mdl` — which also carries the
61+
-- full per-action table.
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
-- Two statements `mxcli check` passed, `exec` wrote without complaint, and only
2+
-- mxbuild refused — one of them by refusing to LOAD the project at all.
3+
-- ako/CapTrackV3 FINDINGS §9 and §46.
4+
--
5+
-- 1. AN UNASSIGNED CREATE (§9):
6+
--
7+
-- CREATE Mod.Region ( Name = 'North' ) COMMIT; -- no `$Var =`
8+
-- mx check -> [CE6005] "The 'Entity' property is required."
9+
-- at Create object activity 'Create Region (Name)'
10+
--
11+
-- The error names the wrong property. `Entity` IS stored. A field-level diff
12+
-- of the assigned and unassigned documents differs in ONE substantive field —
13+
-- `Action.VariableName`, "R" vs "" — everything else being identity (element
14+
-- IDs, flow pointers, StableId). A Mendix Create activity always names its
15+
-- output, and Studio Pro supplies the name itself when you drop one. Patching
16+
-- that single field took the project from 1 error to 0; restoring it took it
17+
-- back to 1.
18+
--
19+
-- mxcli now supplies it too, on Studio Pro's `New<Entity>` convention.
20+
-- Supplied rather than refused, because nothing is guessed: the author said
21+
-- create this entity and did not ask for a handle, which is exactly what an
22+
-- auto-named output is. The generated name is NOT registered as
23+
-- referenceable, so a later `change $NewRegion` stays the error it is.
24+
--
25+
-- 2. A TWO-PART SORT PATH (§46) — the severe one:
26+
--
27+
-- RETRIEVE $Rows FROM Mod.Item SORT BY System.createdDate ASC;
28+
-- mxcli check -> passed
29+
-- mxcli exec -> succeeded, no complaint
30+
-- mx -> System.ArgumentNullException: Value cannot be null.
31+
-- at DomainModels.Refs.AttributeRef.set_AttributeId
32+
--
33+
-- Not a CE code — an unhandled exception with a stack trace. The project is
34+
-- UNLOADABLE, so Studio Pro cannot open it either. The report attributed the
35+
-- exception to `exec`; it is `mx` READING what exec wrote.
36+
--
37+
-- One guard caused it. The qualified branch validated `len(parts) >= 3`, so a
38+
-- two-part path fell through every check and was written verbatim as the
39+
-- sort's AttributeQualifiedName. `System.createdDate` reads as
40+
-- Module.Attribute, names no entity, and Mendix stores a null AttributeId.
41+
--
42+
-- Refused rather than repaired: `Module.Attribute` has no reading that names
43+
-- an entity, and the two candidate repairs — a bare member of the retrieved
44+
-- entity, or a member of the module's like-named entity — mean different
45+
-- things, and only the author knows which.
46+
--
47+
-- WHAT ACTUALLY WORKS FOR A SYSTEM MEMBER, measured on 11.14.0. This is narrower
48+
-- than the report suggests, and worth stating because the obvious reading is
49+
-- wrong:
50+
--
51+
-- sort by <a real attribute> 0 errors
52+
-- sort by createdDate (entity STORES it) 0 errors <- the right spelling
53+
-- sort by createdDate (entity does not) CE1613 <- Mendix is right
54+
-- sort by CreatedDate (wrong case) CE1613 <- Mendix is right
55+
-- sort by System.createdDate UNLOADABLE <- the defect
56+
--
57+
-- A system member is spelled BARE and works. An earlier reading of this — that
58+
-- mxcli could not sort by a system member at all — came from testing against an
59+
-- entity that did not store one.
60+
--
61+
-- Verify:
62+
--
63+
-- mxcli exec create-output-variable-and-sort-path.mdl -p app.mpr
64+
-- mx check -p app.mpr -- 0 errors
65+
--
66+
-- Use `mx check` DIRECTLY, not `mxcli docker check`: that command runs
67+
-- `mx update-widgets` first and can mask a model-level failure.
68+
--
69+
-- Then perturb, one at a time:
70+
--
71+
-- stub freshCreateVariable to return ""
72+
-- -> CE6005 on every unassigned create, and mxcli check still passes.
73+
--
74+
-- change `sort by createdDate` to `sort by System.createdDate`
75+
-- -> refused by exec now. Before the fix: written, and the project could no
76+
-- longer be opened by mxbuild or Studio Pro.
77+
78+
create module CrSort;
79+
/
80+
81+
-- The entity must STORE createdDate for a sort on it to resolve — that is what
82+
-- the AutoCreatedDate pseudo-type sets.
83+
create or modify persistent entity CrSort.Item (
84+
Code: String(20),
85+
CreatedDate: AutoCreatedDate
86+
);
87+
/
88+
89+
create or modify entity CrSort.Region ( Name: String(50) );
90+
/
91+
92+
-- §9: the reported case, twice over. Two unassigned creates of the SAME entity
93+
-- must not end up sharing an output variable — Mendix reports that as CE0119, so
94+
-- a bare "New"+entity would trade one silent defect for another.
95+
create or modify microflow CrSort.ACT_Unassigned ()
96+
begin
97+
CREATE CrSort.Region ( Name = 'North' ) COMMIT;
98+
CREATE CrSort.Region ( Name = 'South' ) COMMIT;
99+
end;
100+
/
101+
102+
-- CONTROL for §9: an assigned create keeps the AUTHOR's name, and that name is
103+
-- still referenceable afterwards. Without this a fix that always generated a name
104+
-- would look correct above.
105+
create or modify microflow CrSort.ACT_Assigned ()
106+
begin
107+
$R = CREATE CrSort.Region ( Name = 'East' ) COMMIT;
108+
CHANGE $R ( Name = 'West' );
109+
COMMIT $R;
110+
end;
111+
/
112+
113+
-- §46: the spelling that works. A bare system member on an entity that stores it.
114+
create or modify microflow CrSort.ACT_SortBare ()
115+
begin
116+
RETRIEVE $Rows FROM CrSort.Item SORT BY createdDate ASC;
117+
LOG INFO 'done';
118+
end;
119+
/
120+
121+
-- CONTROL for §46: an ordinary attribute, and a fully qualified three-part path.
122+
-- The existing belongs-to-the-entity check owns the three-part case and must stay
123+
-- permissive; a fix that refused every dotted path would break this.
124+
create or modify microflow CrSort.ACT_SortOther ()
125+
begin
126+
RETRIEVE $Rows FROM CrSort.Item SORT BY Code DESC;
127+
RETRIEVE $Rows2 FROM CrSort.Item SORT BY CrSort.Item.Code ASC;
128+
LOG INFO 'done';
129+
end;
130+
/
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
-- `ON ERROR CONTINUE` was dropped on most statements and written INVALID on the
2+
-- rest (ako/CapTrackV3 FINDINGS §11).
3+
--
4+
-- The report: the clause parsed, `exec` said nothing, and
5+
-- `describe microflow` showed the retrieve with no error handler:
6+
--
7+
-- RETRIEVE $Users FROM System.User WHERE 'id = ''[%CurrentUser%]''' ON ERROR CONTINUE;
8+
-- describe -> retrieve $Users from System.User where id = '[%CurrentUser%]';
9+
--
10+
-- It vanished at the last hop. The visitor builds the clause and the flow builder
11+
-- set it on the ACTIVITY — a field the metamodel does not have on an
12+
-- ActionActivity and neither engine serializes — while both writers emitted a
13+
-- hardcoded literal "Rollback" on the ACTION, where errorHandlingType actually
14+
-- lives.
15+
--
16+
-- WHICH VALUES MENDIX ACCEPTS. Measured on 11.14.0 by writing each into a stored
17+
-- document of a 0-error project and building. The split is not guessable from the
18+
-- metamodel, where one enum covers every action type:
19+
--
20+
-- action Rollback Continue Abort
21+
-- Retrieve ok ok ok
22+
-- Delete ok ok ok
23+
-- MicroflowCall ok ok CE6035
24+
-- Log ok CE6035 CE6035
25+
-- Create ok CE6035 CE6035
26+
-- Change ok CE6035 CE6035
27+
-- Commit ok CE6035 CE6035
28+
-- Aggregate ok CE6035 CE6035
29+
--
30+
-- Two things follow, and they point in opposite directions.
31+
--
32+
-- 1. THE HARDCODED "Rollback" WAS LOAD-BEARING. A nanoflow's no-clause default is
33+
-- Abort, and Abort is CE6035 on most types — so serializing the builder's
34+
-- value unconditionally would have broken every nanoflow that logs or creates.
35+
-- The clause is therefore carried ONLY when the author wrote one; an
36+
-- un-annotated activity keeps the exact document it has always had.
37+
--
38+
-- 2. CREATE AND COMMIT WERE ALREADY WRITING AN INVALID MODEL. Their builders did
39+
-- set the value on the action, so mxcli wrote `Continue` where mxbuild refuses
40+
-- it, and `mxcli check` passed:
41+
--
42+
-- $T = CREATE EH.Thing ( Code = 'a' ) COMMIT ON ERROR CONTINUE;
43+
-- mx check -> [CE6035] "Error handling type is not supported"
44+
-- at Create object activity 'Create Thing (Code)'
45+
--
46+
-- Now MDL076, refused rather than downgraded: Continue swallows the error and
47+
-- carries on, Rollback aborts the flow, and an author who wrote the clause
48+
-- meant the first.
49+
--
50+
-- A MEASUREMENT TRAP worth keeping. The first version of that table was VACUOUS
51+
-- for Delete and said so only because the probe reported its own patch count: the
52+
-- Delete writer emits no ErrorHandlingType key at all, so setting it changed
53+
-- nothing and mxbuild's silence read as "accepted". The probe was changed to
54+
-- INSERT an absent key.
55+
--
56+
-- Verify:
57+
--
58+
-- mxcli exec error-handling-continue.mdl -p app.mpr
59+
-- mx check -p app.mpr -- 0 errors
60+
-- mxcli -p app.mpr -c "describe microflow ErrH.ACT_Handled"
61+
-- -- all three statements come back carrying `on error continue`
62+
--
63+
-- Then perturb:
64+
--
65+
-- ON ERROR CONTINUE on the retrieve -> stub the builder's action-level assignment
66+
-- describe drops the clause entirely — the reported symptom.
67+
--
68+
-- add `$T = CREATE ErrH.Thing ( Code = 'x' ) ON ERROR CONTINUE;`
69+
-- MDL076 at check time. Before the rule: check passed and mx check gave CE6035.
70+
71+
create module ErrH;
72+
/
73+
74+
create or modify entity ErrH.Thing ( Code: String(20) );
75+
/
76+
77+
create or modify microflow ErrH.SUB_Noop ()
78+
begin
79+
LOG INFO 'noop';
80+
end;
81+
/
82+
83+
-- The three statements Mendix accepts Continue on. All three must round-trip.
84+
create or modify microflow ErrH.ACT_Handled ()
85+
begin
86+
RETRIEVE $Rows FROM ErrH.Thing ON ERROR CONTINUE;
87+
$T = HEAD($Rows);
88+
DELETE $T ON ERROR CONTINUE;
89+
CALL MICROFLOW ErrH.SUB_Noop () ON ERROR CONTINUE;
90+
end;
91+
/
92+
93+
-- CONTROL: the same statements with NO clause. These must keep the document they
94+
-- have always had — the writers' literal — because the builder's value for "no
95+
-- clause" is not always one Mendix accepts. Without this control a fix that
96+
-- serialized the builder's value unconditionally would look correct above.
97+
create or modify microflow ErrH.ACT_Plain ()
98+
begin
99+
RETRIEVE $Rows FROM ErrH.Thing;
100+
$T = HEAD($Rows);
101+
DELETE $T;
102+
CALL MICROFLOW ErrH.SUB_Noop ();
103+
end;
104+
/
105+
106+
-- CONTROL: a NANOFLOW, whose no-clause default is Abort — the value that would
107+
-- have broken the build had it been serialized. An explicit clause on a nanoflow
108+
-- is still the author's.
109+
create or modify nanoflow ErrH.NF_Plain ()
110+
begin
111+
RETRIEVE $Rows FROM ErrH.Thing;
112+
LOG INFO 'from a nanoflow';
113+
end;
114+
/
115+
116+
-- CONTROL for MDL076: a CUSTOM handler is accepted on every action type measured,
117+
-- including the two the rule refuses Continue on. A rule that flagged the clause
118+
-- itself, rather than the Continue variant, would reject this working microflow —
119+
-- and a custom handler is the fix MDL076 suggests.
120+
create or modify microflow ErrH.ACT_CustomHandler ()
121+
begin
122+
$T = CREATE ErrH.Thing ( Code = 'a' ) ON ERROR {
123+
LOG ERROR 'create failed';
124+
};
125+
COMMIT $T ON ERROR {
126+
LOG ERROR 'commit failed';
127+
};
128+
end;
129+
/

0 commit comments

Comments
 (0)