Relationships
#2899 workflow approve on a run that is not suspended prints a fatal error with a stack trace
Opened by hammz · 10/1/2026· Shipped 10/2/2026
Description
swamp workflow approve on a run that is not suspended (for example a run that failed because a parallel gate was rejected) exits 1 with an [FTL] log line and a full JavaScript stack trace, rather than the short user-facing error other workflow commands give in the same situation (resume prints Error: Run <id> is not suspended or failed (status: …)).
Steps to reproduce
Repro workflow (workflows/workflow-e2e-wf.yaml; each step appends to a log so real executions can be counted):
id: <uuid>
name: e2e-wf
version: 1
concurrency: 1
jobs:
- name: a-side
steps:
- name: gate2
task: { type: manual_approval, prompt: "gate2?" }
- name: s
dependsOn: [{ step: gate2, condition: { type: succeeded } }]
task: { type: model_method, modelType: command/shell, modelName: m-s, methodName: execute,
inputs: { run: "echo s >> /tmp/exec.log; sleep 3" } }
- name: main
steps:
- name: gate
task: { type: manual_approval, prompt: "gate?" }
- name: post
dependsOn: [{ step: gate, condition: { type: succeeded } }]
task: { type: model_method, modelType: command/shell, modelName: m-post, methodName: execute,
inputs: { run: "echo post >> /tmp/exec.log" } }
- name: teardown
dependsOn: [{ job: main, condition: { type: always } }]
steps:
- name: t
task: { type: model_method, modelType: command/shell, modelName: m-t, methodName: execute,
inputs: { run: "echo t >> /tmp/exec.log" } }swamp workflow run e2e-wf(suspends atgate2andgate).swamp workflow reject e2e-wf gate2 --run <id>. The run becomesfailed, andmainstaysrunningwithgatewaiting_approval.swamp workflow approve e2e-wf gate --run <id>.
Actual
[FTL] error: Error: Run <id> is not suspended (status: failed)
at error (file:///…/src/cli/commands/workflow_approve.ts:165:17)
at consumeStream (file:///…/src/libswamp/stream.ts:57:11)
at async Command.<anonymous> (file:///…/src/cli/commands/workflow_approve.ts:145:5)
at async Command.execute (https://jsr.io/@cliffy/command/1.0.1/command.ts:2307:7)
…Expected
A one-line user error with no stack trace, ideally with the next step, e.g. Error: Run <id> is not suspended (status: failed). Use 'swamp workflow resume e2e-wf --run <id> --from <step>' to re-enter it. --json mode returns a structured error.
Environment: Linux x86_64. Reproduced with release 20260930.225800.0-sha.1a9b497f and with the swamp-club#2597 branch (e337ad45), so it is not a regression from that fix. Found while end-to-end validating swamp-club#2597.
Shipped
Click a lifecycle step above to view its details.
hammz commented 10/1/2026, 7:55:34 PM
More evidence from end-to-end validation of swamp-club#2895:
workflow rejecthas the same problem. It throws a plainErroratsrc/cli/commands/workflow_reject.ts:158. Approve does the same atsrc/cli/commands/workflow_approve.ts:131and:173(throw new Error(e.error.message)).- A cancelled run hits it too, not only a failed one. Approving or rejecting a gate on a run that
workflow cancelalready cancelled triggers it. --jsonmode leaks the stack into the structured error on stderr. Compareworkflow resume, which returns only{"error": "..."}:{ "error": "Run <id> is not suspended (status: cancelled)", "stack": " at error (file:///…/src/cli/commands/workflow_approve.ts:173:17)\n at consumeStream (…/src/libswamp/stream.ts:57:11)\n …" }
Reproduced with release 20261001.190402.0-sha.543aad7e and with branch 8ae02e19.
Sign in to post a ripple.