coleam00/Archon · error
Cannot signal a non-event workflow wait
Error message
Cannot signal a non-event workflow wait
What it means
A guard error thrown at the top of signalWorkflowWait: after Zod-parsing the waitContext, the code asserts the discriminated `kind` is 'event'. The public signature already types the parameter as the event-only Extract of WorkflowWaitContext, so hitting this at runtime means a non-event wait context (e.g. kind 'time'/'deadline') was passed despite the types, typically via untyped data or an any-cast.
Source
Thrown at packages/core/src/db/workflows.ts:1629
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 =
getDatabaseType() === 'postgresql'
? "metadata->'wait'->>'nodeId'"
: "json_extract(metadata, '$.wait.nodeId')";
const signaledExpr =
getDatabaseType() === 'postgresql'
? "metadata->'wait'->>'signaledAt'"
: "json_extract(metadata, '$.wait.signaledAt')";
const resumeAtExpr =
getDatabaseType() === 'postgresql'
? "metadata->'wait'->>'resumeAt'"
: "json_extract(metadata, '$.wait.resumeAt')";
const signaledAt = new Date().toISOString();View on GitHub (pinned to 0773b97458)
Solutions
- Narrow the wait context to kind === 'event' before calling signalWorkflowWait
- Use the correct signaling API for time/deadline waits (they resume via listDueWorkflowContinuations, not signals)
- Validate the waitContext with workflowWaitContextSchema and check parsed.kind === 'event' yourself first
Example fix
// before
await signalWorkflowWait(runId, waitCtx); // waitCtx.kind === 'time' -> throws
// after
if (waitCtx.kind !== 'event') {
throw new Error(`Cannot signal wait of kind ${waitCtx.kind}; only event waits accept signals`);
}
await signalWorkflowWait(runId, waitCtx); Defensive patterns
Strategy: validation
Validate before calling
import { workflowWaitContextSchema } from '@archon/core';
const parsed = workflowWaitContextSchema.safeParse(waitContext);
if (!parsed.success || parsed.data.kind !== 'event') {
throw new Error(`signalWorkflowWait requires an event wait, got kind=${(waitContext as any)?.kind}`);
} Type guard
function isEventWaitContext(w: WorkflowWaitContext): w is Extract<WorkflowWaitContext, { kind: 'event' }> {
return w.kind === 'event';
} Try / catch
if (!isEventWaitContext(waitContext)) {
log.error({ kind: (waitContext as { kind?: string }).kind }, 'refusing to signal non-event wait');
return { signaled: false };
}
// else proceed; wrap DB errors separately Prevention
- Always narrow on the discriminated `kind` before signaling
- Avoid `any`-typed wait contexts crossing API boundaries
- Load wait contexts through the schema parser, not raw JSON
- Use time/deadline waits via the continuation path, not signals
When it happens
Trigger: Calling signalWorkflowWait(id, waitContext) with a waitContext whose kind is not 'event' — passing a time/deadline wait context, or data loaded from JSON/storage that lost its literal type.
Common situations: Wiring a resume handler to the wrong wait context variable; deserializing wait context from a webhook payload or DB metadata without narrowing kind; using `any` to bypass the Extract<> parameter type.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Invalid --status '${opts.status}'. Valid: ${workflowRunStatu
- Run ${run.id}'s gate ('${approval.type}') only accepts 'appr
- Run ${run.id}'s gate only accepts 'approve' or 'reject' — '$
- Run ${run.id}'s gate does not declare decision '${decision}'
- Node '${consumerId}' binding '${name}': an object value must
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/ca241700064ac86b.
Report an issue: GitHub.