coleam00/Archon · error
Workflow run not found or not in running state (id: ${id})
Error message
Workflow run not found or not in running state (id: ${id}) What it means
completeWorkflowRun() guards its UPDATE with 'WHERE id = $1 AND status = 'running''. If rowCount is 0 the run either does not exist or is not currently running, so the library refuses to stamp completion — protecting terminal state from being overwritten. Unlike cancel, this is a thrown error, not an idempotent no-op.
Source
Thrown at packages/core/src/db/workflows.ts:1231
[id]
);
if ((update.rowCount ?? 0) > 0) {
await insertWorkflowEvent(query, {
workflow_run_id: id,
event_type: 'workflow_completed',
data: completion,
});
}
return update;
});
} catch (error) {
const err = error as Error;
getLog().error({ err }, 'db.workflow_run_complete_failed');
throw new Error(`Failed to complete workflow run: ${err.message}`);
}
if (result.rowCount === 0) {
getLog().warn({ workflowRunId: id }, 'db.workflow_run_complete_no_match');
throw new Error(`Workflow run not found or not in running state (id: ${id})`);
}
}
/**
* Mark a run failed.
*
* Matches `pending` as well as `running`. A run can fail BEFORE it ever transitions to
* running — source capture, artifact setup, and credential resolution all happen against
* a freshly inserted `pending` row — and a `running`-only guard left those rows pending
* forever: no terminal state, no error recorded, and nothing to tell the operator the run
* is dead. Both are non-terminal states owned by this process, so failing either is the
* same decision. Terminal rows still never transition.
*/
export async function failWorkflowRun(
id: string,
error: string,
scheduledResume?: ScheduledWorkflowResume
): Promise<void> {View on GitHub (pinned to 0773b97458)
Solutions
- Fetch the run by id and check its status before completing
- Only call completeWorkflowRun for runs confirmed in 'running' state
- If the run is already terminal, treat completion as done (idempotent) instead of retrying
- If the run is 'pending', first transition it to running per the executor lifecycle, or use failWorkflowRun (which also matches pending)
- Verify the id is the correct workflow run id (not a step/event id)
Example fix
// before
await completeWorkflowRun(runId, { duration_ms });
// after
const run = await getWorkflowRun(runId);
if (run?.status === 'running') {
await completeWorkflowRun(runId, { duration_ms });
} else {
getLog().warn({ runId, status: run?.status }, 'skip complete: not running');
} Defensive patterns
Strategy: validation
Validate before calling
const run = await getWorkflowRun(id);
if (!run || run.status !== 'running') {
throw new Error(`cannot complete run ${id}: status=${run?.status ?? 'missing'}`);
} Type guard
function isRunning(run: { status: string } | undefined | null): boolean {
return run?.status === 'running';
} Try / catch
try {
await completeWorkflowRun(id, { duration_ms });
} catch (err) {
if (err.message.includes('not found or not in running state')) {
const run = await getWorkflowRun(id);
getLog().info({ id, status: run?.status }, 'completion skipped: run not running');
} else { throw err; }
} Prevention
- Check status before terminal transitions
- Make completion idempotent at the call site (skip if already terminal)
- Avoid racing executor completion against cancel/fail paths
- Validate run ids come from the same database they are written to
- Watch for 'db.workflow_run_complete_no_match' warnings as a signal of double completion
When it happens
Trigger: Calling completeWorkflowRun(id, ...) for: an id that was never inserted; a run already 'completed', 'failed', or 'cancelled'; a run still 'pending' (never transitioned to running); or a concurrent terminal transition that won a race.
Common situations: Caller completed the run twice (double completion in executor and a finally block); run failed earlier so failWorkflowRun already set terminal state; operator cancelled the run while it was finishing; typo'd or foreign run id; resumed run rows replaced with new ids.
Related errors
- Detached work stopped, but cancellation did not win the run
- Failed to complete workflow run: ${err.message}
- Failed to fail workflow run: ${err.message}
- Workflow run not found or already terminal (id: ${id})
- Cannot execute run '${detachedPreCreatedRun.id}': it belongs
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/3b9718c0ec3821eb.
Report an issue: GitHub.