coleam00/Archon · error · Error

Node '${node.id}' cannot resume '${sourceNodeId}': source pr

Error message

Node '${node.id}' cannot resume '${sourceNodeId}': source provider '${sourceHandle.provider}' does not match resolved provider '${provider}'.

What it means

When resuming from a named source node, the executor checks that the source node's recorded provider matches the provider resolved for the resuming node. Session handles are provider-specific; forking a session recorded by, say, claude under a codex-resolved node would hand an incompatible session id to the new provider, so it throws.

Source

Thrown at packages/workflows/src/dag-executor.ts:10438

              ? node.context.resume
              : undefined;
            const hasNamedSessionResume = namedResumeSourceNodeId !== undefined;
            let resumeSessionId: string | undefined;
            if (hasNamedSessionResume) {
              const sourceNodeId = namedResumeSourceNodeId;
              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

View on GitHub (pinned to 0773b97458)

Solutions

  1. Pin the same explicit provider on both the source and resuming nodes so resolution matches
  2. Remove the provider override (aiProfile or config default) that makes the resuming node resolve differently
  3. Re-run the whole workflow under the new provider so the source handle is recreated with the matching provider
  4. Update the provider alias/registry so the resolved provider id equals the recorded one

Example fix

// before: only the resuming node pins a provider
- id: research
  persist_session: true
- id: continue
  resume_from: research
  provider: codex
// after: both nodes use the same provider
- id: research
  persist_session: true
  provider: claude
- id: continue
  resume_from: research
  provider: claude
Defensive patterns

Strategy: validation

Validate before calling

const src = ctx.nodeSessionHandles?.get(sourceNodeId);
const resolved = resolveProvider(node, aiProfile, config);
if (src && src.provider !== resolved) throw new Error(`resume provider mismatch: ${src.provider} vs ${resolved}`);

Type guard

function providersMatch(handle: NodeSessionHandle | undefined, provider: string): boolean {
  return handle !== undefined && handle.provider === provider;
}

Try / catch

try {
  await engine.resumeFrom(runId, nodeId, sourceNodeId);
} catch (err) {
  if (err instanceof Error && err.message.includes('does not match resolved provider')) {
    // pin provider on both nodes or re-run under the new provider
  } else throw err;
}

Prevention

When it happens

Trigger: Node B has resume_from: A, but B's provider (explicit node provider, AI profile, or .archon/config.yaml default) resolves to a different provider than the one A actually ran with and recorded in its session handle.

Common situations: Changing the global default provider in .archon/config.yaml after the source node's run; setting an aiProfile that overrides the provider for the resuming node only; renaming provider aliases so resolution no longer matches the source's provider.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/0bf9e1677cb2c3f9. Report an issue: GitHub.