paperclipai/paperclip · error · HarnessReconciliationError
codex_history_read_failed
codex_history_read_failed
Error message
codex_history_read_failed: ${method} requires supported paginated history; ${String(error)} What it means
pages() wraps any error thrown by the paginated history RPC (thread/turns/list or thread/items/list) in a HarnessReconciliationError with code codex_history_read_failed. The library treats a failed history read as fatal for reconciliation because a partial or unsupported provider read must never be evidence that work is idle.
Source
Thrown at packages/paperclip-runner/src/drivers/codex/codex-history.ts:26
async function pages(
transport: Requester,
method: "thread/turns/list" | "thread/items/list",
params: Record<string, unknown>,
identity: (value: Record<string, unknown>) => string,
): Promise<Record<string, unknown>[]> {
const values = new Map<string, Record<string, unknown>>();
const cursors = new Set<string>();
let cursor: string | undefined;
for (let page = 0; page < 10_000; page += 1) {
let response: Record<string, unknown>;
try {
response = await transport.request(method, {
...params,
limit: 100,
...(cursor ? { cursor } : {}),
});
} catch (error) {
throw new HarnessReconciliationError(
`codex_history_read_failed: ${method} requires supported paginated history; ${String(error)}`,
);
}
if (!Array.isArray(response.data))
throw new HarnessReconciliationError(
`codex_history_incomplete: ${method} omitted data`,
);
for (const raw of response.data) {
const value = record(raw);
const id = identity(value);
if (!id)
throw new HarnessReconciliationError(
`codex_history_incomplete: ${method} omitted an identity`,
);
// Later pages can repeat the cursor anchor with its newly completed state.
values.set(id, value);
}
const next = response.nextCursor;View on GitHub (pinned to 01ad858492)
Solutions
- Read the underlying error after 'requires supported paginated history;' to identify the transport failure and fix that root cause (restart app-server, reconnect transport).
- Upgrade the Codex app-server to a version that implements thread/turns/list and thread/items/list with cursor pagination.
- Retry reconciliation after confirming the app-server is healthy (curl the health endpoint or check the process).
- Do not swallow this error: recovery logic depends on failing closed when history cannot be read.
Defensive patterns
Strategy: try-catch
Validate before calling
const healthy = await isAppServerReachable(transport); if (!healthy) throw new Error('codex app-server unreachable before history read'); Type guard
function isHistoryReadFailed(e: unknown): e is HarnessReconciliationError { return e instanceof HarnessReconciliationError && e.message.startsWith('codex_history_read_failed'); } Try / catch
try { const turns = await readCodexTurnMetadata(transport, threadId); } catch (e) { if (isHistoryReadFailed(e)) { log(e.message); await restartAppServerAndRetry(); } else throw e; } Prevention
- Confirm the app-server version supports thread/turns/list and thread/items/list before recovery
- Monitor app-server process health before reconciliation runs
- Include bounded retry with backoff around history reads
- Never treat a failed history read as an empty history
When it happens
Trigger: transport.request for thread/turns/list or thread/items/list rejects: transport disconnected, JSON-RPC method unsupported by the app-server version, timeout, or malformed request params.
Common situations: Older Codex app-server builds that do not implement paginated history methods; the app-server process crashed mid-reconciliation; network/stdio transport failure between runner and provider.
Related errors
- codex_history_incomplete
- thread/read returned a different driver session
- thread/items/list returned a different turn
- codex_history_invalid_cursor
- limit must be a number between 1 and 500
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/0f1bde9a50ada144.
Report an issue: GitHub.