can1357/oh-my-pi · error · Error
Unable to read Codex session ${info.id} at ${info.path}
Error message
Unable to read Codex session ${info.id} at ${info.path} What it means
CodexSessionStore.load() failed to read/parse the Codex rollout file (readJsonLines threw), and rethrows under a message naming the session id and path with the original error attached as `cause`. Check error.cause for the underlying reason (ENOENT, EACCES, JSON syntax error, etc.).
Source
Thrown at packages/coding-agent/src/session/codex-session-store.ts:549
title: indexed?.thread_name,
created,
modified,
});
}
sessions.sort(
(left, right) => right.modified.getTime() - left.modified.getTime() || left.id.localeCompare(right.id),
);
return sessions;
}
/** Converts one Codex rollout into a non-persistent OMP session. */
async load(info: ForeignSessionInfo): Promise<SessionManager> {
if (info.source !== "codex") throw new Error(`Cannot load ${info.source} session with CodexSessionStore`);
let records: Record<string, unknown>[];
try {
records = await readJsonLines(info.path);
} catch (error) {
throw new Error(`Unable to read Codex session ${info.id} at ${info.path}`, { cause: error });
}
if (records.length === 0) throw new Error(`Codex session ${info.id} at ${info.path} is empty or malformed`);
const metadata = records.find(record => record.type === "session_meta" && isRecord(record.payload));
const cwd =
metadata && isRecord(metadata.payload) ? (stringField(metadata.payload, "cwd") ?? info.cwd) : info.cwd;
const manager = SessionManager.inMemory(cwd);
const canonical = canonicalTexts(records);
const converted: ConvertedRecord[] = [];
const toolNames = new Map<string, string>();
let model = "codex";
let fallbackTimestamp = info.created.getTime();
let title = info.title;
for (const record of records) {
const timestamp = timestampMillis(record.timestamp, fallbackTimestamp);
fallbackTimestamp = Math.max(fallbackTimestamp + 1, timestamp);
if (!isRecord(record.payload)) continue;View on GitHub (pinned to 9690622007)
Solutions
- Inspect error.cause to see the real failure (ENOENT vs permission vs JSON parse)
- Confirm the file at info.path exists and each line parses as JSON (head path)
- Re-list Codex sessions to get fresh paths after a Codex upgrade or directory move
- Restore the rollout file from backup or abandon the session
Example fix
// before
try { await codexStore.load(info); } catch (e) { console.log(e.message); }
// after
try { await codexStore.load(info); } catch (e) {
console.error(e.message, 'cause:', e.cause);
const fresh = await codexStore.list();
if (!fresh.some(s => s.id === info.id)) console.error('session file gone; re-list');
} Defensive patterns
Strategy: try-catch
Validate before calling
import * as fs from "node:fs";
// before load:
// if (!fs.existsSync(info.path)) throw new Error(`rollout gone: ${info.path}`);
// probe JSONL: first non-empty line must JSON.parse Type guard
function isUnreadableCodexSession(err: unknown): boolean {
return err instanceof Error && err.message.startsWith('Unable to read Codex session');
} Try / catch
try {
const manager = await codexStore.load(info);
} catch (err) {
if (isUnreadableCodexSession(err)) {
logger.warn('codex rollout unreadable', { path: info.path, cause: String(err.cause) });
return null;
}
throw err;
} Prevention
- Always inspect err.cause — this error wraps the real filesystem/JSON failure
- Re-list sessions after any Codex CLI upgrade; paths can change
- Treat missing rollout files as normal (sessions get cleaned up) in resuming UIs
- Avoid hand-copying rollout files; move them with the directory structure intact
When it happens
Trigger: Calling `codexSessionStore.load(info)` where the rollout file at info.path is missing, unreadable, or contains a line that is not valid JSON — anything that makes readJsonLines reject.
Common situations: Codex CLI moved/renamed its session directory on upgrade so stale listings point at deleted files; partially-written rollout from a crashed Codex run; permissions changed after running under a different user; hand-copied session file is truncated.
Related errors
- Unable to read Claude session ${info.id}: ${detail}
- Short write
- Session append failed and its partial bytes could not be rol
- Too many levels of symbolic links
- {}: {error}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/404f2474092e888d.
Report an issue: GitHub.