{"record":{"id":"94bd0909336668d4","repo":"musistudio/claude-code-router","slug":"archive-not-ready","errorCode":"ARCHIVE_NOT_READY","errorMessage":"Archive ${archiveId} is ${rootSnapshot.status}.","messagePattern":"Archive (.+?) is (.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/gateway/context-archive.ts","lineNumber":229,"sourceCode":"  }, config: ContextArchiveConfig, executor?: ContextArchiveReplayExecutor): Promise<ContextArchiveAskOutput> {\n    const archiveId = input.archiveId.trim();\n    const sessionToken = input.sessionToken.trim();\n    const task = input.task.trim();\n    const toolName = config.toolName || defaultToolName;\n    if (!archiveId || !sessionToken || !task) {\n      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      }","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/gateway/context-archive.ts#L211-L247","documentation":"Thrown when the archive snapshot exists and is unexpired but its status field is anything other than \"ready\" — typically \"pending\" or \"failed\". The gateway refuses to replay a snapshot that never finished persisting or that errored during creation.","triggerScenarios":"Calling ask() while the archive is still being written (race: create() has not resolved); replaying a snapshot whose archival step previously failed; status flipped to a non-ready state by a concurrent writer.","commonSituations":"Fire-and-forget archive creation followed by an immediate replay; crashed archive jobs leaving rows in pending/failed; testing against partially seeded stores.","solutions":["Wait for archive creation to fully complete (await the create promise / poll until status === 'ready') before calling ask","If status is 'failed', re-run the archival and generate a new snapshot","Inspect the snapshot record to see which non-ready state it is in and fix the underlying write path"],"exampleFix":"// before\nawait archive.create(request); // not awaited\nawait archive.ask(archiveId, token, task); // ARCHIVE_NOT_READY\n\n// after\nconst { archiveId, sessionToken } = await archive.create(request); // fully persisted, status 'ready'\nawait archive.ask(archiveId, sessionToken, task);","handlingStrategy":"validation","validationCode":"const snap = store.get(archiveId);\nif (!snap || snap.status !== 'ready') {\n  await waitFor(() => store.get(archiveId)?.status === 'ready', { timeout: 30_000 });\n}\nawait archive.ask(archiveId, sessionToken, task);","typeGuard":"function isReadyArchive(s: { status: string } | undefined): s is { status: 'ready' } {\n  return s?.status === 'ready';\n}","tryCatchPattern":"try { await archive.ask(id, token, task); }\ncatch (e) { if (e.code === 'ARCHIVE_NOT_READY') { /* poll status, back off, or recreate */ } throw e; }","preventionTips":["Always await archive creation fully before issuing replay requests","Poll snapshot.status until 'ready' with a timeout instead of assuming","Treat non-ready status at ask time as a bug in your archival flow, not a runtime condition"],"tags":["archive","state-machine","gateway"],"backgroundTag":"resource-not-ready","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}