coleam00/Archon · error
Cannot abandon run with status '${run.status}'. Only running
Error message
Cannot abandon run with status '${run.status}'. Only running, paused, or failed runs can be abandoned. What it means
abandonWorkflow intentionally diverges from the resumable-status constant: it blocks only the two terminal states 'completed' and 'cancelled', since those runs are already finished and cannot be discarded. Running, paused, and failed runs can be abandoned to cancel them and cascade-cancel descendants.
Source
Thrown at packages/core/src/operations/workflow-operations.ts:472
// Reclaim only when our cancel won the CAS. A miss means another lifecycle
// owner now controls the run and its environment.
if (cancelled) await reclaimCancelledRunContainer(run);
return { run, cancelled, cancelledDescendants, cascadeFailures, blockedParentRunId };
}
/**
* Abandon a workflow run (marks it as cancelled).
*
* Running, paused, AND failed runs can be abandoned. A `failed` run is terminal
* per TERMINAL_WORKFLOW_STATUSES but remains resumable, so the user must be able
* to discard it — hence the inline check here intentionally diverges from that
* constant and blocks only the two non-resumable terminal states.
*/
export async function abandonWorkflow(runId: string): Promise<AbandonWorkflowResult> {
const run = await getRunOrThrow(runId, 'operations.workflow_abandon_lookup_failed');
if (run.status === 'completed' || run.status === 'cancelled') {
throw new Error(
`Cannot abandon run with status '${run.status}'. Only running, paused, or failed runs can be abandoned.`
);
}
const result = await cancelRunAndCleanup(run, workflowDb.cancelWorkflowRun);
return {
run: result.run,
cancelled: result.cancelled,
cascadeFailures: result.cascadeFailures,
blockedParentRunId: result.blockedParentRunId,
};
}
export interface AbandonConversationRunsResult {
/** Runs this call actually took to 'cancelled'. */
abandoned: number;
/**
* First cancelled run that left a parent outside the conversation-scoped
* mutation paused blocked-on-child (stranded parent id), or null. The userView on GitHub (pinned to 0773b97458)
Solutions
- Check status before abandoning: only call abandonWorkflow for 'running', 'paused', or 'failed' runs.
- Treat 'completed' runs as permanent history — archive or ignore them rather than discarding.
- If you get this on 'cancelled', the abandon already happened; no action needed.
- Filter cleanup jobs to non-terminal statuses via the run listing query.
Example fix
// before
for (const run of runs) await abandonWorkflow(run.id);
// after
for (const run of runs) {
if (run.status !== 'completed' && run.status !== 'cancelled') {
await abandonWorkflow(run.id);
}
} Defensive patterns
Strategy: validation
Validate before calling
if (run.status === 'completed' || run.status === 'cancelled') skip; else await abandonWorkflow(run.id);
Type guard
function isAbandonable(run: WorkflowRun): boolean {
return run.status !== 'completed' && run.status !== 'cancelled';
} Try / catch
try { await abandonWorkflow(runId); }
catch (e) {
if ((e as Error).message.startsWith("Cannot abandon run with status")) {
console.info('Run already terminal; nothing to abandon.');
} else throw e;
} Prevention
- Filter cleanup/abandon jobs to running, paused, or failed runs only.
- Treat completed/cancelled runs as immutable history.
- Make abandon idempotent: a second abandon on a cancelled run means the first succeeded.
When it happens
Trigger: Calling abandonWorkflow on a run whose status is 'completed' or 'cancelled'.
Common situations: A cleanup script sweeping old runs hits already-completed ones; an operator double-abandons a run that was already cancelled; automation retries abandon after a first success.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot reject run with status '${run.status}'. Only paused r
- Cannot resume run with status '${run.status}'. Only failed o
- Cannot execute run '${detachedPreCreatedRun.id}': it belongs
- Dry-run failed; missing stubs: ${blockingMissingStubs.join('
- result.error
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/9eb754bc1257c255.
Report an issue: GitHub.