Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneeszack

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: 1
swamp workflow run foreach-input-gate --input env=prod

Actual

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
02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 7 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

10/9/2026, 5:43:32 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
zack assigned zack10/9/2026, 5:26:06 PM

Sign in to post a ripple.