coleam00/Archon · error · Error
Node '${node.id}' cannot resume '${sourceNodeId}': resolved
Error message
Node '${node.id}' cannot resume '${sourceNodeId}': resolved provider '${provider}' does not support immutable session forks. What it means
Beyond provider identity, session resume requires the resolved provider to declare both sessionResume and immutable session forks (sessionFork === true) in getCapabilities(). If the resolved provider lacks these, the executor cannot safely fork the source session and throws before starting the node.
Source
Thrown at packages/workflows/src/dag-executor.ts:10444
const sourceHandle = ctx.nodeSessionHandles?.get(sourceNodeId);
if (sourceHandle === undefined) {
throw new Error(
`Node '${node.id}' cannot resume '${sourceNodeId}': the completed source has no available provider session.`
);
}
if (sourceHandle.sessionId.trim() === '') {
throw new Error(
`Node '${node.id}' cannot resume '${sourceNodeId}': the completed source has no available provider session.`
);
}
if (sourceHandle.provider !== provider) {
throw new Error(
`Node '${node.id}' cannot resume '${sourceNodeId}': source provider '${sourceHandle.provider}' does not match resolved provider '${provider}'.`
);
}
const caps = ctx.deps.getAgentProvider(provider).getCapabilities();
if (!caps.sessionResume || caps.sessionFork !== true) {
throw new Error(
`Node '${node.id}' cannot resume '${sourceNodeId}': resolved provider '${provider}' does not support immutable session forks.`
);
}
resumeSessionId = sourceHandle.sessionId;
}
// Legacy scalar/default selection — parallel or context:fresh → always fresh.
// Parallel layers always get fresh sessions; explicit 'fresh' context also forces it.
// 'shared' forces continuation. Default: fresh for parallel, inherited for sequential.
// isFreshSequential controls in-run threading (lastSequentialSession).
// Cross-provider guard (#1992): a session id can only be resumed by the provider
// that created it, so the cursor is threaded only into nodes that resolve to the
// SAME provider — on a provider change the node starts fresh instead of failing
// (Claude) or silently cold-falling-back (Codex) on a foreign session id.
//
// A composed workflow's ENTRY node is the third fresh case (#1764). Standalone,
// that node runs first and has no cursor to inherit; composed, it would silently
// pick up the session of whatever the parent ran before it — the same fileView on GitHub (pinned to 0773b97458)
Solutions
- Use a provider whose capabilities include sessionResume and sessionFork: true (e.g. claude) for the resuming node
- Remove the named resume (resume_from) so the node starts its own fresh session
- For custom/mock providers, implement getCapabilities() returning { sessionResume: true, sessionFork: true } and real fork behavior
- Check the provider registry/capability docs to confirm fork support before wiring session-resume nodes
Example fix
// before: provider without fork support
getCapabilities() { return { sessionResume: true } }
// after
getCapabilities() { return { sessionResume: true, sessionFork: true } } Defensive patterns
Strategy: validation
Validate before calling
const caps = ctx.deps.getAgentProvider(provider).getCapabilities();
if (!caps.sessionResume || caps.sessionFork !== true) throw new Error(`${provider} cannot fork sessions; drop resume_from or switch provider`); Type guard
function supportsSessionFork(caps: ProviderCapabilities): boolean {
return caps.sessionResume === true && caps.sessionFork === true;
} Try / catch
try {
await engine.resumeFrom(runId, nodeId, sourceNodeId);
} catch (err) {
if (err instanceof Error && err.message.includes('does not support immutable session forks')) {
// start a fresh session instead of forking
} else throw err;
} Prevention
- Check getCapabilities() before authoring resume_from wiring
- For mock providers, declare sessionResume/sessionFork and implement fork behavior
- Prefer providers with documented immutable-fork semantics (e.g. claude) for resume chains
When it happens
Trigger: Node B resumes from A's session while B's resolved provider's getCapabilities() returns sessionResume:false or sessionFork !== true (e.g. a provider that supports resume but not forks, or a mock provider with default caps).
Common situations: Switching to a provider that implements sessions differently (no fork semantics); using a custom or mock provider in tests without declaring sessionFork; a provider capability regression after an SDK upgrade.
Related errors
- Node '${node.id}' cannot resume '${sourceNodeId}': the compl
- Node '${node.id}' cannot resume '${sourceNodeId}': source pr
- Node '${node.id}' has persist_session: true but resolved pro
- Provider${incompatible.size === 1 ? '' : 's'} '${list}' cann
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/81cce7a8aa76542a.
Report an issue: GitHub.