{"record":{"id":"19b53885bd9a91ad","repo":"stablyai/orca","slug":"terminal-history-recovery-generation-changed","errorCode":null,"errorMessage":"terminal_history_recovery_generation_changed","messagePattern":"terminal_history_recovery_generation_changed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/daemon/history-manager.ts","lineNumber":68,"sourceCode":"    schedulePendingSessionTreeRemovals(this.basePath)\n  }\n\n  async openSession(sessionId: string, opts: OpenSessionOptions): Promise<void> {\n    let recoveryFreeze = opts.recoveryFreeze\n    try {\n      this.disabledSessions.delete(sessionId)\n      const dir = join(this.basePath, getHistorySessionDirName(sessionId))\n      recoveryFreeze ??= await this.freezeForRecovery(sessionId)\n      const activeFreeze = this.requireRecoveryFreeze(sessionId, recoveryFreeze)\n\n      if (opts.quarantineUnreadableRecovery) {\n        quarantineTerminalHistorySession(this.basePath, sessionId, activeFreeze.fingerprint ?? null)\n      } else if (hasTerminalHistoryRecoveryProtection(this.basePath, sessionId)) {\n        throw new Error('terminal_history_recovery_protected')\n      } else if (\n        fingerprintTerminalHistorySession(this.basePath, sessionId) !== activeFreeze.fingerprint\n      ) {\n        throw new Error('terminal_history_recovery_generation_changed')\n      }\n      this.recoveryFreezes.delete(sessionId)\n      mkdirSync(dir, { recursive: true })\n\n      const meta: SessionMeta = {\n        cwd: opts.cwd,\n        cols: opts.cols,\n        rows: opts.rows,\n        startedAt: new Date().toISOString(),\n        endedAt: null,\n        exitCode: null\n      }\n      writeFileSync(join(dir, 'meta.json'), JSON.stringify(meta, null, 2))\n\n      if (!opts.quarantineUnreadableRecovery) {\n        // Why: a crash before the first checkpoint must not replay a cleanly ended prior session.\n        for (const staleFile of [\n          join(dir, 'checkpoint.json'),","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/daemon/history-manager.ts#L50-L86","documentation":"terminal_history_recovery_generation_changed in openSession: the current fingerprint of the session history directory does not match the fingerprint captured at freeze time. The directory tree changed between freeze and open (concurrent write, external modification, or corruption), so opening would mix generations. The freeze is abandoned and the session's history is disabled.","triggerScenarios":"openSession where fingerprintTerminalHistorySession(basePath, sessionId) differs from activeFreeze.fingerprint, with no quarantine requested and no protection marker. The dir was modified after the recovery freeze was taken.","commonSituations":"Another process (or a leftover writer) modified the history directory between freezeForRecovery and openSession; filesystem metadata changed (inode/mtime) due to AV scanning or a sync tool; a crash left a partially-written directory.","solutions":["Re-freeze and re-open once the directory is quiescent (no concurrent writers).","If quarantine is appropriate, pass quarantineUnreadableRecovery to quarantine the changed generation and start fresh.","Ensure no other process touches the history base path during recovery (disable sync/AV on that dir).","Accept that history is disabled for this session and continue without it."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"function isRecoveryGenerationChanged(e: unknown): boolean {\n  return e instanceof Error && e.message === 'terminal_history_recovery_generation_changed'\n}","tryCatchPattern":"try {\n  await history.openSession(id, opts)\n} catch (e) {\n  if (e instanceof Error && e.message === 'terminal_history_recovery_generation_changed') {\n    // history disabled internally; continue without it, or re-quarantine\n    await history.openSession(id, { ...opts, quarantineUnreadableRecovery: true })\n  } else { throw e }\n}","preventionTips":["Freeze and open within the same quiet window so the directory does not change generation.","Keep concurrent writers/checkpoints off the session dir during recovery.","Exclude the history base path from sync/AV tools that alter mtimes."],"tags":["history","recovery","integrity","generation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}