{"record":{"id":"1ca4de6bff61531b","repo":"stablyai/orca","slug":"failed-to-persist-codex-session-index-heal-outcome","errorCode":null,"errorMessage":"Failed to persist Codex session index-heal outcome for ${thread.threadId}","messagePattern":"Failed to persist Codex session index-heal outcome for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/codex/codex-session-index-heal.ts","lineNumber":250,"sourceCode":"      return\n    }\n    if (/SQLITE_(?:BUSY|LOCKED)|database (?:is )?(?:busy|locked)/i.test(message)) {\n      // Why: an active Codex process can briefly own sqlite; leave the id off\n      // the ledger and abort this pass so a later startup resumes it.\n      throw error\n    }\n    summary.failedThreads += 1\n    recordHealOutcome(paths, thread, 'failed')\n  }\n}\n\nfunction recordHealOutcome(\n  paths: CodexSessionIndexHealPaths,\n  thread: PendingHealThread,\n  outcome: HealLedgerOutcome\n): void {\n  if (!appendHealLedgerRecord(paths, thread.threadId, outcome, thread.auditRecordId)) {\n    throw new Error(`Failed to persist Codex session index-heal outcome for ${thread.threadId}`)\n  }\n}\n\nfunction resolveHealWorkLimit(value: number | undefined, maximum: number): number {\n  if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {\n    return maximum\n  }\n  return Math.min(Math.floor(value), maximum)\n}\n\nfunction buildNativeHealInvocation(\n  systemCodexHomePath: string,\n  timeoutMs: number\n): CodexAppServerInvocation {\n  const command = resolveCodexCommand()\n  const { spawnCmd, spawnArgs } = getSpawnArgsForWindows(command, ['app-server'])\n  return {\n    command: spawnCmd,","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/codex/codex-session-index-heal.ts#L232-L268","documentation":"Thrown when appendHealLedgerRecord returned false for a thread's heal outcome — the JSONL append to the heal ledger (healLedgerPath) failed. Recording the outcome is critical: without it, a healed thread would be re-healed forever, and a failed one would never be retried. So a failed append aborts healOneThread rather than silently losing the record.","triggerScenarios":"The heal ledger file is not writable (permissions, read-only mount); the parent directory was removed; disk is full so the append can't flush; the ledger write hit an OS error that appendHealLedgerRecord swallows and returns false for.","commonSituations":"Orca state directory permissions changed mid-run; disk filled during a large heal pass; the state dir is on a network mount that dropped; an antivirus quarantined the ledger file.","solutions":["Check write permissions on dirname(paths.healLedgerPath).","Free disk space.","Ensure the Orca state directory persists across the run (not a tmpdir that was cleared).","On Windows, exclude the Orca state dir from antivirus locking.","If the ledger is corrupt, back it up and remove it so the next pass rebuilds from the audit log."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import { access, constants } from 'node:fs/promises'\nimport { dirname } from 'node:path'\ntry {\n  await access(dirname(paths.healLedgerPath), constants.W_OK)\n} catch {\n  // ledger dir not writable; skip this heal pass rather than aborting per-thread\n}","typeGuard":"function isHealLedgerPersistError(error: unknown): boolean {\n  return error instanceof Error && error.message.startsWith('Failed to persist Codex session index-heal outcome for ')\n}","tryCatchPattern":"try {\n  recordHealOutcome(paths, thread, outcome)\n} catch (error) {\n  if (isHealLedgerPersistError(error)) {\n    // abort this heal pass; the thread stays off the ledger and retries next pass\n    summary.outcome = 'aborted'\n  } else throw error\n}","preventionTips":["Keep the Orca state directory writable and on a stable mount.","Ensure disk space during large heal passes.","Exclude the state dir from antivirus locking on Windows.","A failed append leaves the thread unrecorded; it retries on the next startup automatically."],"tags":["codex","index-heal","ledger","filesystem","persistence"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}