can1357/oh-my-pi · error · Error

Claude session ${info.id} contains no readable records

Error message

Claude session ${info.id} contains no readable records

What it means

ClaudeSessionStore.load() found that the session file exists and has nonzero size (stats.size > 0) but zero records could be parsed out of it by collectForeignJsonRecords. The library throws this to distinguish 'file present but entirely unparseable' from the generic read failure above.

Source

Thrown at packages/coding-agent/src/session/claude-session-store.ts:359

		}
		return sessions.sort(
			(left, right) => right.modified.getTime() - left.modified.getTime() || left.path.localeCompare(right.path),
		);
	}

	/** Loads and converts a Claude transcript while preserving its source tree and timestamps. */
	async load(info: ForeignSessionInfo): Promise<SessionManager> {
		if (info.source !== this.source) throw new Error(`Cannot load ${info.source} session with ClaudeSessionStore`);
		let records: ForeignJsonRecord[];
		let stats: fsTypes.Stats;
		try {
			[records, stats] = await Promise.all([collectForeignJsonRecords(info.path), fs.stat(info.path)]);
		} catch (error) {
			const detail = error instanceof Error ? error.message : String(error);
			throw new Error(`Unable to read Claude session ${info.id}: ${detail}`);
		}
		if (records.length === 0 && stats.size > 0)
			throw new Error(`Claude session ${info.id} contains no readable records`);

		const sourceParents = new Map<string, string | null>();
		let sourceCwd: string | undefined;
		let sourceTitle: string | undefined;
		let aiTitle: string | undefined;
		for (const { value } of records) {
			const uuid = stringField(value, "uuid");
			if (uuid) sourceParents.set(uuid, stringField(value, "parentUuid") ?? null);
			if (!sourceCwd) sourceCwd = stringField(value, "cwd");
			if (value.type === "custom-title") sourceTitle = stringField(value, "customTitle") ?? sourceTitle;
			if (value.type === "ai-title") aiTitle = stringField(value, "aiTitle") ?? aiTitle;
		}

		const manager = SessionManager.inMemory(sourceCwd ?? info.cwd);
		const sourceTails = new Map<string, string>();
		const usedIds = new Set<string>();
		const toolNames = new Map<string, string>();
		let lastModel: string | undefined;

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the file (head -c 500 path) to confirm whether it is valid JSONL at all
  2. Restore the session file from backup or let Claude Code regenerate it
  3. Delete the corrupt file and re-list sessions so the dead entry disappears
  4. Update the OMP package — a newer parser may accept the changed Claude format

Example fix

// before
await store.load({ id, path: '/home/me/.claude/projects/x/session.jsonl', source: 'claude' });
// after
const stat = await fs.stat(path);
const text = await Bun.file(path).text();
if (!text.trim().startsWith('{')) throw new Error(`corrupt session file: ${path}`);
await store.load({ id, path, source: 'claude' });
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from "node:fs";
export function isPlausibleClaudeSessionFile(path: string): boolean {
  try {
    const stat = fs.statSync(path);
    if (stat.size === 0) return false;
    const head = fs.readFileSync(path, 'utf8').slice(0, 256).trimStart();
    return head.startsWith('{'); // JSONL should start with a JSON object
  } catch {
    return false;
  }
}
// call: if (!isPlausibleClaudeSessionFile(info.path)) skip;

Type guard

function isNoReadableRecordsError(err: unknown): boolean {
  return err instanceof Error && /contains no readable records/.test(err.message);
}

Prevention

When it happens

Trigger: Calling load(info) on a Claude session JSONL whose every line fails to parse as a valid JSON record — e.g. the file is binary, truncated mid-write, empty JSON shells, or an unrecognized/rotated format.

Common situations: Disk-full crash left a corrupt transcript; a backup/sync tool truncated the file; Claude Code format change made old parsers reject every record; someone hand-edited or copied the wrong file into the sessions directory.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/d792356d2eb6b722. Report an issue: GitHub.