{"record":{"id":"34f0de388cbe16ea","repo":"coleam00/Archon","slug":"node-node-id-cannot-resume-sourcenodeid","errorCode":null,"errorMessage":"Node '${node.id}' cannot resume '${sourceNodeId}': the completed source has no available provider session.","messagePattern":"Node '(.+?)' cannot resume '(.+?)': the completed source has no available provider session\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/workflows/src/dag-executor.ts","lineNumber":10428,"sourceCode":"              ctx.aiProfile,\n              ctx.workflowPreset,\n              resolveAiConfigText,\n              ctx.warnedProviderConflicts,\n              ctx.execContext\n            );\n\n            // 5. Determine session. An explicit named ancestor has first priority and\n            // is independent of the ambient sequential cursor and parallel-layer reset.\n            const namedResumeSourceNodeId = isNodeContextResume(node.context)\n              ? node.context.resume\n              : undefined;\n            const hasNamedSessionResume = namedResumeSourceNodeId !== undefined;\n            let resumeSessionId: string | undefined;\n            if (hasNamedSessionResume) {\n              const sourceNodeId = namedResumeSourceNodeId;\n              const sourceHandle = ctx.nodeSessionHandles?.get(sourceNodeId);\n              if (sourceHandle === undefined) {\n                throw new Error(\n                  `Node '${node.id}' cannot resume '${sourceNodeId}': the completed source has no available provider session.`\n                );\n              }\n              if (sourceHandle.sessionId.trim() === '') {\n                throw new Error(\n                  `Node '${node.id}' cannot resume '${sourceNodeId}': the completed source has no available provider session.`\n                );\n              }\n              if (sourceHandle.provider !== provider) {\n                throw new Error(\n                  `Node '${node.id}' cannot resume '${sourceNodeId}': source provider '${sourceHandle.provider}' does not match resolved provider '${provider}'.`\n                );\n              }\n              const caps = ctx.deps.getAgentProvider(provider).getCapabilities();\n              if (!caps.sessionResume || caps.sessionFork !== true) {\n                throw new Error(\n                  `Node '${node.id}' cannot resume '${sourceNodeId}': resolved provider '${provider}' does not support immutable session forks.`\n                );","sourceCodeStart":10410,"sourceCodeEnd":10446,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/dag-executor.ts#L10410-L10446","documentation":"A node configured with a named session resume (`resume:` pointing at a completed source node) looks up that source node's recorded session handle in ctx.nodeSessionHandles. If the source completed but stored no handle at all, there is no provider session to fork, so the executor fails fast instead of silently starting a fresh session.","triggerScenarios":"Node B declares a resume from completed node A, but A ran with persist_session disabled, A's session handle was never recorded (e.g. A completed in an older run/attempt before handle persistence), or the handle map lost the entry across a run restart.","commonSituations":"Adding `resume_from`/named session wiring to a node whose source predates session persistence; resuming a run where the source node's handle was persisted under a different scope key; provider changed for the source so no handle was captured.","solutions":["Set persist_session: true on the SOURCE node so its provider session handle is recorded on completion","Re-run the workflow from the beginning so the source node completes again and writes a fresh session handle","Confirm the resume source node id matches exactly the node that completed in this run (not another run or renamed node)","Check the store's getWorkflowNodeSession/persisted scope key configuration if handles are persisted across runs"],"exampleFix":"// before: source has no persist_session\n- id: research\n  prompt: \"...\"\n- id: continue\n  resume_from: research\n// after\n- id: research\n  prompt: \"...\"\n  persist_session: true\n- id: continue\n  resume_from: research","handlingStrategy":"validation","validationCode":"const handle = ctx.nodeSessionHandles?.get(sourceNodeId);\nif (!handle) throw new Error(`source ${sourceNodeId} has no session handle; set persist_session on it and re-run`);","typeGuard":"function hasSessionHandle(handles: Map<string, NodeSessionHandle> | undefined, id: string): handles is Map<string, NodeSessionHandle> {\n  return handles?.get(id) !== undefined;\n}","tryCatchPattern":"try {\n  await engine.resumeFrom(runId, nodeId, sourceNodeId);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('no available provider session')) {\n    // re-run workflow so the source node records a handle\n  } else throw err;\n}","preventionTips":["Always set persist_session: true on nodes that others resume from","Keep node ids stable; renames orphan recorded handles","After upgrading providers, re-run workflows rather than resuming old runs"],"tags":["session-resume","workflow-config","provider-session"],"backgroundTag":"missing-session-handle","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}