coleam00/Archon · error
Failed to abandon workflow run ${run.id}: ${err.message}
Error message
Failed to abandon workflow run ${run.id}: ${err.message} What it means
cancelRunAndCleanup wraps the underlying cancellation of a run during abandon; if the cancel call throws for any reason, the error is logged (with type and runId under 'operations.workflow_abandon_failed') and rethrown as 'Failed to abandon workflow run <id>: <cause>'. This is a boundary translation that preserves the original message for diagnostics.
Source
Thrown at packages/core/src/operations/workflow-operations.ts:440
interface AbandonAttemptResult extends AbandonWorkflowResult {
cancelledDescendants: number;
}
async function cancelRunAndCleanup(
run: WorkflowRun,
cancelRun: CancelWorkflowRun
): Promise<AbandonAttemptResult> {
let cancelled: boolean;
try {
({ cancelled } = await cancelRun(run.id));
} catch (error) {
const err = error as Error;
getLog().error(
{ err, errorType: err.constructor.name, runId: run.id },
'operations.workflow_abandon_failed'
);
throw new Error(`Failed to abandon workflow run ${run.id}: ${err.message}`);
}
// The same cancellation policy applies to descendants. This keeps `/reset`'s
// resumable-only ownership boundary intact through the complete run tree.
let cascadeFailures = 0;
let cancelledDescendants = 0;
if (cancelled) {
({ cancelled: cancelledDescendants, failures: cascadeFailures } = await cascadeCancelChildren(
run.id,
cancelRun
));
}
const blockedParentRunId = cancelled ? await findParentBlockedOn(run) : null;
// 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 };View on GitHub (pinned to 0773b97458)
Solutions
- Read the underlying cause in err.message and the 'operations.workflow_abandon_failed' log entry to fix the root issue (DB connectivity, lock, disk).
- Retry the abandon once the database issue is resolved — abandon is safe to re-attempt on a still-abandonable run.
- Verify no concurrent process is mutating the same run (check run status before retrying).
- If the DB is persistently failing, check database health/permissions before further operations.
Example fix
// before
await abandonWorkflow(runId); // may throw raw DB error wrapped here
// after
try {
await abandonWorkflow(runId);
} catch (e) {
logger.error({ runId, cause: (e as Error).message });
// fix DB issue, then retry
} Defensive patterns
Strategy: try-catch
Validate before calling
await db.ping(); // verify database reachability before bulk abandon operations
Try / catch
try { await abandonWorkflow(runId); }
catch (e) {
const msg = (e as Error).message;
if (msg.startsWith('Failed to abandon workflow run')) {
logger.error({ runId, cause: msg }, 'abandon failed; inspect operations.workflow_abandon_failed log and retry after fixing DB');
} else throw e;
} Prevention
- Monitor database health (connections, locks, disk) before bulk run management.
- Avoid concurrent abandon of the same run from multiple operators/scripts.
- Check the 'operations.workflow_abandon_failed' structured log for err type and runId.
When it happens
Trigger: workflowDb.cancelWorkflowRun (or the injected cancel function) throws while abandoning a run — e.g. database write failure, lock contention, or a concurrent modification of the run row.
Common situations: SQLite/Postgres connection loss or busy-lock during abandon; two operators abandoning the same run simultaneously; disk-full or migration mismatch preventing the status write.
Related errors
- Failed to cancel fan-out run: ${err.message}
- Failed to pause workflow run: ${err.message}
- Failed to pause workflow run for wait: ${err.message}
- Failed to get workflow run: ${err.message}
- Workflow run '${runId}' references codebase '${codebaseId}',
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/9dbbe4bfff78ef9e.
Report an issue: GitHub.