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

  1. Read the underlying error after 'requires supported paginated history;' to identify the transport failure and fix that root cause (restart app-server, reconnect transport).
  2. Upgrade the Codex app-server to a version that implements thread/turns/list and thread/items/list with cursor pagination.
  3. Retry reconciliation after confirming the app-server is healthy (curl the health endpoint or check the process).
  4. 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

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


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/0f1bde9a50ada144. Report an issue: GitHub.