Relationships
#3217 workflow run reports a forEach-expanded approval gate as waiting on a nested run
Opened by zack · 10/9/2026· Shipped 10/9/2026
Description
When a workflow suspends on a manual_approval step that was expanded by forEach, swamp workflow run reports the suspension as a wait on a nested run. The step is an approval gate of the run's own: the same output prints its prompt and its approve/reject commands, swamp workflow approvals lists it, and swamp workflow approve accepts it.
A manual_approval step without forEach is reported correctly.
Steps to reproduce
In an initialized repo, add this workflow and run it:
id: 7c1f0b2e-5d7a-4c3b-9e21-3027a0b1c2d3
name: foreach-input-gate
tags: {}
inputs:
type: object
properties:
env:
type: string
required:
- env
jobs:
- name: main
steps:
- name: approve-${{ self.env }}
forEach:
item: env
in: "${{ [inputs.env] }}"
task:
type: manual_approval
prompt: "Deploy?"
dependsOn: []
weight: 0
dependsOn: []
weight: 0
version: 1swamp workflow run foreach-input-gate --input env=prodActual
system │ Starting workflow foreach-input-gate · 17:25:16 UTC
main │ start 17:25:16 UTC
main │ waiting approval required: "Deploy?"
main │ To approve: swamp workflow approve foreach-input-gate approve-prod --run <run-id>
main │ To reject: swamp workflow reject foreach-input-gate approve-prod --run <run-id>
system │ Suspended workflow foreach-input-gate — step approve-prod waits on a nested run · 17:25:16 UTC
system │ Once it finishes: swamp workflow resume foreach-input-gate --run <run-id>The closing hint, "Once it finishes: swamp workflow resume …", is misleading: nothing finishes until someone approves the gate.
Expected
What the same step prints without forEach (same binary):
system │ Suspended workflow plain-gate — awaiting approval on step approve-prod · 17:25:17 UTC
system │ To approve: swamp workflow approve plain-gate approve-prod --run <run-id>
system │ After approval: swamp workflow resume plain-gate --run <run-id>Likely cause
waitsOnNestedRun() in src/presentation/renderers/workflow_run.ts, added in 3aa438b6 (swamp-club#3110, PR #2954). It returns true when the suspended event has no nested, no wait, an empty prompt, and the named step's status in the run view is not waiting. The forEach-expanded gate evidently meets that condition, though it is a gate with a non-empty prompt ("Deploy?"). I have not traced which of the two inputs is wrong for an expanded step (the event's prompt, or the step lookup/status by expanded name).
Impact
swamp-uat's Adversarial Tier 6 fails on every run: tests/cli/adversarial/step_name_control_chars_test.ts, "swamp workflow run and approvals print a forEach step name from an item value with its control characters escaped", which asserts awaiting approval on step <name>. First seen on swamp-uat run 37963547703 (PR #605, unrelated change). Reproduces 3/3 locally.
Environment
- swamp 20261009.154711.0-sha.8df63c9b
- Linux x86_64
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.