{"record":{"id":"dfc7ab07faffd375","repo":"musistudio/claude-code-router","slug":"archive-replay-unavailable-dfc7ab","errorCode":"ARCHIVE_REPLAY_UNAVAILABLE","errorMessage":"The gateway replay executor is not available.","messagePattern":"The gateway replay executor is not available\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/gateway/context-archive.ts","lineNumber":235,"sourceCode":"      throw contextArchiveError(\"ARCHIVE_INVALID_ARGUMENT\", `${toolName} requires archive_id, session_token, and task.`);\n    }\n\n    const store = this.store(config);\n    const rootSnapshot = store.get(archiveId);\n    if (!rootSnapshot) {\n      throw contextArchiveError(\"ARCHIVE_NOT_FOUND\", `Archive ${archiveId} does not exist or has expired.`);\n    }\n    if (rootSnapshot.expiresAt !== undefined && rootSnapshot.expiresAt <= Date.now()) {\n      throw contextArchiveError(\"ARCHIVE_EXPIRED\", `Archive ${archiveId} has expired.`);\n    }\n    if (rootSnapshot.status !== \"ready\") {\n      throw contextArchiveError(\"ARCHIVE_NOT_READY\", `Archive ${archiveId} is ${rootSnapshot.status}.`);\n    }\n    if (!constantTimeEqual(rootSnapshot.tokenHash, sha256(sessionToken))) {\n      throw contextArchiveError(\"ARCHIVE_ACCESS_DENIED\", \"The archive session token is invalid.\");\n    }\n    if (!executor) {\n      throw contextArchiveError(\"ARCHIVE_REPLAY_UNAVAILABLE\", \"The gateway replay executor is not available.\");\n    }\n\n    const lineage = store.lineage(archiveId, maxLineageReplayDepth);\n    const searchedGenerations: number[] = [];\n    let lastInsufficientAnswer: { answer: string; snapshot: ArchiveSnapshot } | undefined;\n    for (const snapshot of lineage) {\n      if (snapshot.expiresAt !== undefined && snapshot.expiresAt <= Date.now()) {\n        continue;\n      }\n      if (snapshot.status !== \"ready\") {\n        continue;\n      }\n      const answer = await replayArchiveSnapshot(snapshot, task, config, executor);\n      searchedGenerations.push(snapshot.generation);\n      if (isInsufficientArchiveAnswer(answer) && snapshot.parentArchiveId) {\n        lastInsufficientAnswer = { answer, snapshot };\n        continue;\n      }","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/gateway/context-archive.ts#L217-L253","documentation":"Thrown when the replay path is entered but no replay executor was provided to the archive service. The executor is the component that actually re-issues the archived request to the upstream agent; without it, replay cannot proceed.","triggerScenarios":"Constructing the ContextArchive service/gateway without wiring an executor (or passing undefined), then calling ask() on a valid, ready, token-matching archive.","commonSituations":"DI misconfiguration where the executor binding is optional and silently omitted; test harnesses constructing the service with partial dependencies; refactors that removed executor registration.","solutions":["Provide/restore the replay executor when constructing the archive service","Check the service construction path in your composition root or DI container for a missing/optional registration","Add a startup assertion that the executor is bound before enabling the archive feature"],"exampleFix":"// before\nconst archive = new ContextArchive({ storagePath }); // no executor\nawait archive.ask(id, token, task); // ARCHIVE_REPLAY_UNAVAILABLE\n\n// after\nconst archive = new ContextArchive({ storagePath }, replayExecutor);\nawait archive.ask(id, token, task);","handlingStrategy":"validation","validationCode":"if (!executor) throw new Error('replay executor required for archive replay');\nconst archive = new ContextArchive(config, executor);","typeGuard":"function hasExecutor(x: unknown): x is ReplayExecutor {\n  return !!x && typeof x === 'object' && 'answer' in x;\n}","tryCatchPattern":"try { await archive.ask(id, token, task); }\ncatch (e) { if (e.code === 'ARCHIVE_REPLAY_UNAVAILABLE') { /* fail fast at startup instead */ } throw e; }","preventionTips":["Assert executor presence in your composition root at startup, not lazily at replay time","Make the executor a required constructor parameter in your own wrapper","Add an integration test that performs one full replay in CI"],"tags":["archive","dependency-injection","configuration"],"backgroundTag":"missing-required-dependency","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}