coleam00/Archon · error
Failed to defer workflow continuation: ${err.message}
Error message
Failed to defer workflow continuation: ${err.message} What it means
Thrown by deferWorkflowContinuation when the UPDATE that writes `continuation_retry_at` backoff metadata fails. The update is guarded (only matches a paused wait with exact resumeAt/nodeId or a failed scheduled resume with matching attempt), but this error is reserved for SQL/driver failures, which are logged under `db.workflow_continuation_defer_failed`. A zero-row match is silent, not an error.
Source
Thrown at packages/core/src/db/workflows.ts:1617
try {
await pool.query(
`UPDATE remote_agent_workflow_runs
SET metadata = ${dialect.jsonMerge('metadata', 2)}
WHERE id = $1 AND ((status = 'paused' AND ${waitResumeAt} = $3 AND ${waitNodeId} = $4)
OR (status = 'failed' AND ${scheduledResumeAt} = $3
AND ${scheduledTriggeredAt} IS NULL AND ${scheduledAttempt} = $5))`,
[
id,
JSON.stringify({ continuation_retry_at: retryAt }),
cursor.resumeAt,
cursor.kind === 'wait' ? cursor.nodeId : null,
cursor.kind === 'quota' ? cursor.attempt : null,
]
);
} catch (error) {
const err = error as Error;
getLog().error({ err, workflowRunId: id }, 'db.workflow_continuation_defer_failed');
throw new Error(`Failed to defer workflow continuation: ${err.message}`);
}
}
/** Atomically record the signal for one exact paused event wait. */
export async function signalWorkflowWait(
id: string,
waitContext: Extract<WorkflowWaitContext, { kind: 'event' }>,
payload?: unknown
): Promise<{ signaled: boolean }> {
const parsedWaitContext = workflowWaitContextSchema.parse(waitContext);
if (parsedWaitContext.kind !== 'event') {
throw new Error('Cannot signal a non-event workflow wait');
}
const eventExpr =
getDatabaseType() === 'postgresql'
? "metadata->'wait'->>'event'"
: "json_extract(metadata, '$.wait.event')";
const nodeExpr =View on GitHub (pinned to 0773b97458)
Solutions
- Inspect the `db.workflow_continuation_defer_failed` log for the real driver error
- Retry the defer — it is idempotent metadata written only on an exact state match
- Verify the dialect's jsonMerge implementation against the running database engine
- Check for row-lock contention and serialize continuation processing if needed
Example fix
// before
await deferWorkflowContinuation(id, retryAt, cursor); // throws on transient failure
// after
try {
await deferWorkflowContinuation(id, retryAt, cursor);
} catch (e) {
logger.warn({ runId: id, err: e }, 'defer failed; continuation will be retried on next scan');
} Defensive patterns
Strategy: retry
Validate before calling
// pre-check the run still matches the cursor before deferring const run = await getWorkflowRun(id); const matches = run != null && ( (run.status === 'paused' && run.metadata?.wait?.resumeAt === cursor.resumeAt) || (run.status === 'failed' && run.metadata?.scheduled_resume?.resumeAt === cursor.resumeAt) );
Type guard
function isContinuationCursor(c: unknown): c is WorkflowContinuationCursor {
return typeof c === 'object' && c !== null && 'kind' in c && 'resumeAt' in (c as Record<string, unknown>);
} Try / catch
try {
await deferWorkflowContinuation(id, retryAt, cursor);
} catch (error) {
log.warn({ id, err: error }, 'defer failed; next scan will pick the continuation up');
// safe to swallow: the write is pure backoff metadata
} Prevention
- Treat defer as best-effort backoff; never crash the worker over it
- Avoid many concurrent defers on the same run to prevent lock contention
- Validate cursor shape (kind, resumeAt, nodeId/attempt) before calling
- Keep dialect jsonMerge implementations covered by tests for both engines
When it happens
Trigger: Calling deferWorkflowContinuation(id, retryAt, cursor) when the transaction fails, the connection drops, dialect jsonMerge produces invalid SQL, or a lock conflict on the run row times out.
Common situations: DB contention while many continuations back off concurrently; dialect mismatch (e.g. jsonMerge variant unsupported by the actual engine); transient network failure mid-backoff write.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Failed to get workflow run: ${err.message}
- Workflow run '${runId}' references codebase '${codebaseId}',
- Failed to load codebase '${codebaseId}' for workflow run '${
- Failed to complete workflow run: ${err.message}
- Workflow run not found or not in running state (id: ${id})
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/bb08be7e09ec666a.
Report an issue: GitHub.