Skip to content

fix(executor): subflow edge keys mismatch#4202

Merged
icecrasher321 merged 2 commits intostagingfrom
fix/consec-subflow-key-issue
Apr 16, 2026
Merged

fix(executor): subflow edge keys mismatch#4202
icecrasher321 merged 2 commits intostagingfrom
fix/consec-subflow-key-issue

Conversation

@icecrasher321
Copy link
Copy Markdown
Collaborator

Summary

Test this workflow. Consecutive loops case with empty followed by populated breaks due to edge key mismatch.

Manual trigger

[Seed] (Function)
return { empty: [], populated: [1, 2, 3] }

[LoopEmpty] forEach <seed.result.empty>
└─ body: Function return <loop.currentItem>
↓ (loop-end-source → loop container)
[LoopWork] forEach <seed.result.populated>
└─ body: Function return <loop.currentItem>

Type of Change

  • Bug fix

Testing

Tested pre and post fix. Added unit tests.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Apr 16, 2026 8:39pm

Request Review

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 16, 2026

PR Summary

Medium Risk
Touches core DAG edge-activation/reset logic and subflow container logging, which can affect execution ordering and loop/parallel readiness; changes are well-covered by new regressions but could impact complex workflows.

Overview
Fixes a loop-reset regression where EdgeManager.clearDeactivatedEdgesForNodes could incorrectly re-activate externally cascade-deactivated edges due to substring matching, causing subsequent loop iterations (and consecutive loops) to stall with phantom incoming dependencies.

Adds targeted regression tests around loop sentinel start/end readiness and internal-vs-external edge reset behavior, and refactors loop/parallel orchestrators to emit a new emitSubflowSuccessEvents BlockLog/onComplete callback on successful container completion so trace-span grouping can use the user-configured container names (with new trace-span tests covering this).

Reviewed by Cursor Bugbot for commit 5e143b6. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 16, 2026

Greptile Summary

This PR fixes a stall bug where consecutive loops — an empty one followed by a populated one — would cause the second loop to hang after its first iteration. The root cause was clearDeactivatedEdgesForNodes using includes(-${nodeId}-) which inadvertently matched edge keys where the loop's sentinel was the target (not the source), re-activating cascade-deactivated external edges and leaving a phantom pending incoming that blocked isNodeReady. The fix narrows the check to startsWith(${nodeId}-) so only edges originating inside the loop are cleared on reset. As a secondary change, a new emitSubflowSuccessEvents utility deduplicates the onBlockComplete/BlockLog emission for successful containers across both loop and parallel orchestrators, and ensures the user-configured block name propagates to trace spans.

Confidence Score: 5/5

Safe to merge — the one-line edge-key fix is well-reasoned, backed by three targeted regression tests, and the remaining finding is a P2 style cleanup.

All substantive findings are P2 or lower (unused return type). The core bug fix is correct, well-documented, and fully tested. The utility refactor cleanly deduplicates loop/parallel completion logic without changing observable behavior.

apps/sim/executor/utils/subflow-utils.ts — minor unused Promise return type in emitSubflowSuccessEvents

Important Files Changed

Filename Overview
apps/sim/executor/execution/edge-manager.ts Core bug fix: narrows clearDeactivatedEdgesForNodes to only remove edges whose SOURCE is inside the loop, preventing external cascade-deactivated edges from being incorrectly re-activated during loop reset.
apps/sim/executor/execution/edge-manager.test.ts Three new regression tests covering the fixed bug, the post-reset loop-continue path, and a guard ensuring internal loop edges are still cleared — thorough coverage for the edge-key matching change.
apps/sim/executor/utils/subflow-utils.ts New emitSubflowSuccessEvents utility deduplicates the onBlockComplete/BlockLog logic for successful containers; minor issue with an unused Promise return type.
apps/sim/executor/orchestrators/loop.ts Clean refactor: inlined onBlockComplete block replaced by emitSubflowSuccessEvents call, removing ~25 lines of duplicated logic.
apps/sim/executor/orchestrators/parallel.ts Same refactor as loop.ts — inlined onBlockComplete replaced by emitSubflowSuccessEvents, consistent with loop orchestrator.
apps/sim/lib/logs/execution/trace-spans/trace-spans.ts Comment updated to reflect that container BlockLogs are now emitted on success (not just skip/error), enabling resolveContainerName to use the user-configured name.
apps/sim/lib/logs/execution/trace-spans/trace-spans.test.ts Two new concurrent tests verifying that the user-configured loop/parallel container name appears in the trace span when a success BlockLog is present.

Sequence Diagram

sequenceDiagram
    participant External as External Node
    participant SentinelStart as Loop Sentinel-Start
    participant Body as Loop Body
    participant SentinelEnd as Loop Sentinel-End
    participant EdgeMgr as EdgeManager

    Note over External,EdgeMgr: Empty upstream loop cascades deactivation
    External->>EdgeMgr: processOutgoingEdges({selectedOption: 'else'})
    EdgeMgr->>EdgeMgr: deactivateEdgeAndDescendants(external-node, sentinel-start)
    Note over EdgeMgr: deactivatedEdges = {external-node-sentinel-start-...}

    Note over External,EdgeMgr: Populated loop resets for next iteration
    EdgeMgr->>EdgeMgr: clearDeactivatedEdgesForNodes({sentinel-start, body, sentinel-end})
    Note over EdgeMgr: OLD: includes(-sentinel-start-) also matched<br/>external-node-sentinel-start-... → wrongly cleared!
    Note over EdgeMgr: NEW: startsWith(sentinel-start-) only matches<br/>edges where sentinel-start is SOURCE → external edge preserved

    SentinelEnd->>EdgeMgr: processOutgoingEdges({selectedRoute: loop_continue})
    EdgeMgr->>SentinelStart: incomingEdges: only loop_continue active
    Note over SentinelStart: countActiveIncomingEdges = 0 → READY ✓
Loading

Reviews (1): Last reviewed commit: "fix(executor): subflow edge keys mismatc..." | Re-trigger Greptile

Comment thread apps/sim/executor/utils/subflow-utils.ts Outdated
@icecrasher321
Copy link
Copy Markdown
Collaborator Author

bugbot run

@icecrasher321 icecrasher321 merged commit 6aa6346 into staging Apr 16, 2026
14 checks passed
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 5e143b6. Configure here.

@waleedlatif1 waleedlatif1 deleted the fix/consec-subflow-key-issue branch April 17, 2026 21:20
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