You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Canvas annotations inside ON ERROR { } are accepted and silently ignored, and describe emits none of them — the error branch's layout is unwritable and lost on round-trip #991
Mendix 11.12.1, MPR v2. The repro below runs on a blank project created with mx create-project --app-name ReproApp, so nothing project-specific is involved.
Scenario
We generate nanoflows from MDL and steer the canvas with @position, @anchor and @curve. Our house convention (enforced by a layout linter) is that an error-handling
branch descends in a column under the activity that owns the handler: the edge leaves
the source's bottom (oci=2) and enters the destination's top (dci=0), with the
conventional control vectors (0,+30) / (0,−30).
Every annotation inside the block below is deliberately non-default, so that "it came
out right" cannot be confused with "the annotation was applied". The third statement is the
control: the same annotations at top level.
CREATE MICROFLOW MyFirstModule.SUB_Callee ()
BEGIN
@position(200, 200)
LOG INFO NODE 'Repro''callee';
@position(400, 200)
RETURN;
END;
/-- Repro: annotations inside ON ERROR
CREATE NANOFLOW MyFirstModule.NF_ErrorBranch ()
BEGIN
@position(240, 200)
CALL MICROFLOW MyFirstModule.SUB_Callee() ON ERROR WITHOUT ROLLBACK {
@position(240, 380)
@anchor(from: right, to: left)
@curve(from: (0, 30), to: (0, -30))
LOG ERROR NODE 'Repro''handled';
};
@position(560, 200)
RETURN;
END;
/-- Control: the same annotations at top level
CREATE NANOFLOW MyFirstModule.NF_TopLevelControl ($A: Integer)
RETURNS IntegerAS $R
BEGIN
@position(200, 200)
@anchor(from: bottom, to: top)
@curve(from: (0, 30), to: (0, -30))
DECLARE $R Integer= $A +1;
@position(200, 400)
RETURN $R;
END;
/
mxcli check repro.mdl -p ReproApp.mpr --references -> Syntax OK (4 statements), All references valid
mxcli exec repro.mdl -p ReproApp.mpr -> Created ... (exit 0)
mx check ReproApp.mpr -> The app contains: 0 errors.
Expected output
The handler edge stores the authored sides and control vectors — OriginConnectionIndex = 1, DestinationConnectionIndex = 3, OriginControlVector = 0;30, DestinationControlVector = 0;-30 — exactly as the control
nanoflow does with the same annotations, and describe round-trips them.
Experienced output
Read back from the stored BSON (mxcli bson dump --type nanoflow --object …), v0.20.0:
Everything passes mxcli check, mxcli exec reports success, and mx check reports 0
errors. No headless view shows the loss.
(Side note, unrelated to this issue but visible in the control: to: top stored dci=3
rather than 0 — that is #990, reproduced here independently on 11.12.1.)
Second half: describe emits nothing for the branch
Round-tripping NF_ErrorBranch with v0.20.0:
create or modify nanoflow MyFirstModule.NF_ErrorBranch ()
begin
@position(240, 200)
call microflow MyFirstModule.SUB_Callee() on error without rollback {
log error node 'Repro' 'handled';
};
@position(560, 200)
return;
end;
/
The log error inside the block comes back with no @position — even though the stored RelativeMiddlePoint is 240;380, i.e. a value the writer did accept. So describe → exec does not merely fail to improve the branch's layout: it discards the position that
was there, collapsing the handler back onto auto-placement.
Same on a hand-drawn flow: a nanoflow with three error branches aligned by hand in Studio
Pro describes with @position / @curve on every top-level activity and none on the
activities inside on error without rollback { … }.
Impact
This is the one annotation gap with no second tool behind it. Microflow layout can be
patched through Studio Pro's PED API (ped_update_document), but that API does not write
nanoflows — so for a nanoflow the MDL surface is the only writer, and an error branch's
geometry is unreachable from any script.
Concretely it makes two layout rules mutually unsatisfiable. The branch must descend in a
column (each handler gets its own x, so two handlers cannot fight over one horizontal
lane); a descending edge needs curvature or it renders as a bare diagonal; curvature cannot
be written inside the block. We measured four different drawings of the same two-handler
nanoflow — 4 lint findings (branch horizontal, violating the column rule), 6 (branch in
a column, the correct drawing), 10 (handler rejoining the merge). None reaches zero, and the
residue is entirely (0,0) control vectors on edges MDL cannot name.
Because describe also drops the branch's @position, regenerating a nanoflow a human has
aligned in Studio Pro destroys that work silently — Replaced nanoflow: on stdout, mx check 0 errors, and the canvas quietly worse. Same class as the mapping round-trips
fixed in 0.20.0: the statement reported success and the model came back different.
Honour @anchor / @curve / @merge on statements inside an ON ERROR block — the
error edge, the edges between handler activities, and the rejoin edge.
Emit @position (and non-default @anchor / @curve) for activities inside the block
in describe, so the round-trip stops losing geometry that is already stored.
mxcli version
Reproduced on both:
mxcli diag:Mendix version
Mendix 11.12.1, MPR v2. The repro below runs on a blank project created with
mx create-project --app-name ReproApp, so nothing project-specific is involved.Scenario
We generate nanoflows from MDL and steer the canvas with
@position,@anchorand@curve. Our house convention (enforced by a layout linter) is that an error-handlingbranch descends in a column under the activity that owns the handler: the edge leaves
the source's bottom (
oci=2) and enters the destination's top (dci=0), with theconventional control vectors
(0,+30)/(0,−30).Every annotation inside the block below is deliberately non-default, so that "it came
out right" cannot be confused with "the annotation was applied". The third statement is the
control: the same annotations at top level.
Expected output
The handler edge stores the authored sides and control vectors —
OriginConnectionIndex = 1,DestinationConnectionIndex = 3,OriginControlVector = 0;30,DestinationControlVector = 0;-30— exactly as the controlnanoflow does with the same annotations, and
describeround-trips them.Experienced output
Read back from the stored BSON (
mxcli bson dump --type nanoflow --object …), v0.20.0:@anchor(from: right, to: left)→ asked(1,3), stored(2,0)— the writer's default.@curve(from: (0,30), to: (0,-30))→ stored(0,0)/(0,0).@merge(x, y)on the same statement is likewise ignored — see Microflow canvas: container Size, edge waypoints and merge positions are not writable — hand-quality layout impossible via MDL #884 Problem 3, where I'veadded the measurement (the rejoin merge lands exactly on the End event, not ~80px after).
Everything passes
mxcli check,mxcli execreports success, andmx checkreports 0errors. No headless view shows the loss.
(Side note, unrelated to this issue but visible in the control:
to: topstoreddci=3rather than
0— that is #990, reproduced here independently on 11.12.1.)Second half:
describeemits nothing for the branchRound-tripping
NF_ErrorBranchwith v0.20.0:The
log errorinside the block comes back with no@position— even though the storedRelativeMiddlePointis240;380, i.e. a value the writer did accept. Sodescribe→execdoes not merely fail to improve the branch's layout: it discards the position thatwas there, collapsing the handler back onto auto-placement.
Same on a hand-drawn flow: a nanoflow with three error branches aligned by hand in Studio
Pro describes with
@position/@curveon every top-level activity and none on theactivities inside
on error without rollback { … }.Impact
This is the one annotation gap with no second tool behind it. Microflow layout can be
patched through Studio Pro's PED API (
ped_update_document), but that API does not writenanoflows — so for a nanoflow the MDL surface is the only writer, and an error branch's
geometry is unreachable from any script.
Concretely it makes two layout rules mutually unsatisfiable. The branch must descend in a
column (each handler gets its own
x, so two handlers cannot fight over one horizontallane); a descending edge needs curvature or it renders as a bare diagonal; curvature cannot
be written inside the block. We measured four different drawings of the same two-handler
nanoflow — 4 lint findings (branch horizontal, violating the column rule), 6 (branch in
a column, the correct drawing), 10 (handler rejoining the merge). None reaches zero, and the
residue is entirely
(0,0)control vectors on edges MDL cannot name.Because
describealso drops the branch's@position, regenerating a nanoflow a human hasaligned in Studio Pro destroys that work silently —
Replaced nanoflow:on stdout,mx check0 errors, and the canvas quietly worse. Same class as the mapping round-tripsfixed in 0.20.0: the statement reported success and the model came back different.
Related
Problems 2 and 3. Filed against 0.17.0, before
@curveexisted; this report is narrowerand current: the annotations now exist and parse, and are dropped inside
ON ERROR.@anchor 'to: top'maps to the wrong stored port at top level. Different failure(wrong value written vs. no value written), likely the same side-mapping code.
@mergeround-trip.Suggested resolution
@anchor/@curve/@mergeon statements inside anON ERRORblock — theerror edge, the edges between handler activities, and the rejoin edge.
@position(and non-default@anchor/@curve) for activities inside the blockin
describe, so the round-trip stops losing geometry that is already stored.annotation that parses is worse than a syntax error, which is the argument the
@sizenote in Microflow canvas: container Size, edge waypoints and merge positions are not writable — hand-quality layout impossible via MDL #884 already makes.
Happy to test a fix build.