n8n-io/n8n · info · Error
Checkpoint for runId ${this.runId} has status '${state.statu
Error message
Checkpoint for runId ${this.runId} has status '${state.status}' — crashResume only accepts step checkpoints; use resume() for suspended runs What it means
Informational notice that the workflow contains no trigger node, so it can only be run manually. This is allowed but usually unintended for production workflows. Suppressed entirely when validationOptions.allowNoTrigger is set.
Source
Thrown at packages/@n8n/agents/src/runtime/loop/agent-runtime.ts:516
/**
* Durable-log RFC (resilience phase): re-drive a run from a `running`-status
* step checkpoint after a process crash. Unlike resume(), there is no
* pending tool call to settle — the checkpoint was written at a step
* boundary — so the loop re-enters directly at the next model call.
* `contextNotes` are appended as user messages before the model call: the
* host uses them to surface interrupted tool calls ("effect unverified —
* verify before retrying") and undrained steering corrections recovered
* from its durable event log. Tool calls are never re-executed mechanically.
*/
async crashResume(
options: { runId: string; contextNotes?: string[] } & ExecutionOptions,
): Promise<StreamResult> {
this.runId = options.runId;
const state = await this.runState.loadForCrashResume(this.runId);
if (!state) throw new Error(`No checkpoint found for runId: ${this.runId}`);
if (state.status !== 'running') {
throw new Error(
`Checkpoint for runId ${this.runId} has status '${state.status}' — crashResume only accepts step checkpoints; use resume() for suspended runs`,
);
}
// A claimed HITL resume also persists as 'running' but still carries its
// pending tool calls; re-driving it would skip settling them. Step
// checkpoints are always written with empty pendingToolCalls.
if (Object.keys(state.pendingToolCalls).length > 0) {
throw new Error(
`Checkpoint for runId ${this.runId} has pending tool calls — crashResume only accepts step checkpoints`,
);
}
const list = AgentMessageList.deserialize(state.messageList);
this.context.hydrateDeferredToolsFromList(list);
await hydrateFileParts(list.messages(), this.config.fileStore, {
threadId: state.persistence?.threadId,
});
View on GitHub (pinned to 5ac6606e81)
Solutions
- Add a trigger node (scheduleTrigger, manualTrigger, webhookTrigger, etc.) to make the workflow runnable on its own.
- If this is a sub-workflow invoked by a parent, set the allowNoTrigger validation option to suppress the notice.
- Confirm the trigger node's type string is recognised as a trigger if you believe one is already present.
Example fix
// before — no trigger
set({ name: 'Do Work', assignments: { assignments: [{ id: '1', name: 'x', value: 1, type: 'number' }] } });
// after
const t = scheduleTrigger({ name: 'Daily' });
t.to(set({ name: 'Do Work', assignments: { assignments: [{ id: '1', name: 'x', value: 1, type: 'number' }] } })); Defensive patterns
Strategy: validation
Validate before calling
import { isTriggerNodeType } from './trigger-detection';
function hasTrigger(nodes: Array<{ type: string }>): boolean {
return nodes.some((n) => isTriggerNodeType(n.type));
}
// before validating:
if (!hasTrigger(allNodes) && !validationOptions.allowNoTrigger) {
// add a trigger, or set allowNoTrigger for sub-workflows
} Prevention
- Set allowNoTrigger only for genuinely callable sub-workflows.
- Make trigger addition the first step of workflow generation.
- Confirm the trigger type string is classified as a trigger.
When it happens
Trigger: None of the workflow's nodes has a type classified as a trigger by isTriggerNodeType, and ctx.validationOptions.allowNoTrigger is falsy.
Common situations: Building a sub-workflow intended to be called by another workflow (use allowNoTrigger); an AI builder omitted the trigger; testing a partial graph.
Related errors
- Cannot decrease maxIterations when resuming a run. Expected
- No checkpoint found for runId: ${this.runId}
- Checkpoint for runId ${this.runId} has pending tool calls —
- Reflector output must be valid JSON
- invalid_graph
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/b1d1f3b7c444f56b.
Report an issue: GitHub.