Skip to content

fix: loop-back retry error handler to merge before source activity (#506)#507

Open
hjotha wants to merge 1 commit intomendixlabs:mainfrom
hjotha:submit/rest-retry-loop-error-handler
Open

fix: loop-back retry error handler to merge before source activity (#506)#507
hjotha wants to merge 1 commit intomendixlabs:mainfrom
hjotha:submit/rest-retry-loop-error-handler

Conversation

@hjotha
Copy link
Copy Markdown
Contributor

@hjotha hjotha commented May 4, 2026

Summary

  • When a call activity's custom error handler ends with an IF where exactly one branch terminates (via raise error or return) and the other performs retry actions, the builder now reproduces the Studio Pro authored topology: a merge is inserted just before the source activity, and the non-terminating branch's tail loops back to that merge. Previously the builder emitted a linear topology that placed the merge after the source, moving the call's output variable out of scope for downstream activities and triggering CE0108 "Variable X is defined but not in scope" on mx check.
  • isRetryLoopErrorHandler detects the pattern (trailing IF with exactly-one-terminating branch) and routes through a new buildRetryLoopErrorHandler helper. Non-retry error handlers still use the existing forward-merge path.
  • New flowBuilder.incomingRedirect field lets the outer loop in buildFlowGraph redirect the next inbound flow to the pre-source merge instead of the source activity itself.

Reproduction & validation

Minimal MDL:

create or modify microflow M.Retry ($In: String) returns String begin
  declare $RetryCount Integer = 0;
  $R = call microflow M.Helper(...) on error without rollback {
    log error node @M.LogNode 'retry';
    if $RetryCount<1 then
      set $RetryCount = $RetryCount+1;
    else
      raise error;
    end if;
  };
  return $In;
end;
/

Before this PR: mxcli exec followed by mx check reports CE0108. After this PR: mx check reports 0 errors. Additional downstream mx check diagnostics that surface after the scope fix are pre-existing describer/builder issues in retrieve-chain-over-mapping and are independent of this change.

Test plan

  • Unit test TestRetryLoopErrorHandlerLoopsBackToSource — verifies the retry shape produces prev->merge->source, tail->merge, and no direct prev->source edge.
  • Unit test TestNonRetryErrorHandlerUsesForwardMerge — guards the opposite path (non-retry handlers must not introduce a merge).
  • go test ./... passes.
  • Reproduction MDL yields mx check errors = 0; before this PR it reported CE0108.

🤖 Generated with Claude Code

…ource

When a call activity with a custom error handler has a body ending in an
IF where exactly one branch terminates (via RAISE ERROR or RETURN), the
authored Studio Pro topology uses a merge placed before the source
activity with the non-terminating branch looping back to that merge —
implementing a retry pattern. MDL has no surface syntax for the loop-back
edge, so previously the builder emitted a linear topology that placed
the merge after the source, which moved subsequent activities'
references to the call's output variable out of scope and triggered
CE0108 "Variable X is defined but not in scope" in mx check.

Detect the pattern via isRetryLoopErrorHandler (last statement is an IF
with exactly one terminating branch) and build the loop-back topology
directly in buildRetryLoopErrorHandler: a new merge is placed just left
of the source activity, the handler tail's exit connects to the merge
as a plain SequenceFlow (the IsErrorHandler edge is already on the
source → first-handler-activity connection), and fb.incomingRedirect
redirects the outer loop's inbound flow to terminate at the merge.

A repro (mxcli exec of a rest-call-with-retry microflow into a blank
MPR, then mx check) now reports 0 errors on the simple case; before this
fix it reported CE0108. Non-retry error handlers still use the existing
forward-merge path.

Related: tracked in mendixlabs#506.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

AI Code Review

Critical Issues

None found.

Moderate Issues

None found.

Minor Issues

None found.

What Looks Good

  • Bug fix correctness: The PR correctly addresses CE0108 by detecting retry-loop error handlers (trailing IF with exactly one terminating branch) and inserting a merge before the source activity with loop-back topology. The unit tests validate the expected flow graph structure (prev→merge→source, tail→merge).
  • Test coverage: New comprehensive unit tests (TestRetryLoopErrorHandlerLoopsBackToSource, TestNonRetryErrorHandlerUsesForwardMerge) verify both the fix and the preservation of non-retry error handler behavior. The tests check for correct merge placement and absence of direct prev→source edges.
  • Code clarity: The added helper functions (isRetryLoopErrorHandler, bodyTerminates, buildRetryLoopErrorHandler) are well-named and self-documenting. The incomingRedirect field purpose is clearly explained in comments.
  • Scope adherence: Changes are isolated to microflow flow graph construction (cmd_microflows_builder*.go) with no unrelated modifications. The fix follows the existing patterns in the file.
  • Robustness: The retry-loop detection correctly handles nested IF statements via recursive bodyTerminates. Non-retry paths remain unaffected (forward-merge only).

Recommendation

Approve the PR. The change is minimal, well-tested, and precisely solves the reported CE0108 scope issue for retry-loop error handlers while maintaining backward compatibility for other error handler patterns. No checklist violations were identified.


Automated review via OpenRouter (Nemotron Super 120B) — workflow source

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.

2 participants