paperclipai/paperclip · error
Codex turn response omitted turn.id
Error message
Codex turn response omitted turn.id
What it means
After sending the turn/start JSON-RPC request, startTurn reads response.turn.id; if it is missing or empty, no turn was actually accepted by the Codex app-server, so the method rolls back the optimistic turn-started state and throws this error. The rollback ensures semantic/terminal waiters released by the settled turn/start cannot observe an active turn for a request the provider never accepted.
Source
Thrown at packages/paperclip-runner/src/drivers/codex/codex-harness-session.ts:262
throw error;
} finally {
this.turnStartPending = false;
// Release a terminal notification that arrived and parked itself
// while this turn/start was in flight. This runs before turn.accepted
// below, in the same synchronous continuation, so a released waiter
// never observes the terminal turn ahead of turn.accepted.
releaseTurnStartSettled();
}
this.assertProtocolIntegrity();
const turn = record(response.turn);
const turnId = text(turn.id);
if (turnId.length === 0) {
// A start notification is only optimistic until the response validates.
// Clear it before released semantic/terminal waiters can observe an
// active turn for a request that was never accepted.
this.activeTurnId = null;
this.turnStarted = false;
throw new Error("Codex turn response omitted turn.id");
}
if (this.activeTurnId !== null && this.activeTurnId !== turnId) {
this.failProtocol(
"turn_start_mismatch",
"turn/start response disagreed with turn/started",
);
throw new Error("Codex turn identity changed during start");
}
this.activeTurnId ??= turnId;
if (dispositionOnlyRecovery) {
this.dispositionOnlyRecoveryTurnId = turnId;
}
this.emit("turn.accepted", { turnId }, { turnId });
if (this.interruptQueued) {
this.interruptQueued = false;
await this.#sendInterrupt(turnId, "queued_before_start");
}
return {View on GitHub (pinned to 01ad858492)
Solutions
- Check the Codex app-server version and pin one whose turn/start response includes turn.id; update paperclip-runner if a schema change requires a fix.
- Log the raw turn/start response to confirm the shape; if a proxy/middleware is in the path, verify it is not dropping the turn field.
- Retry startTurn after verifying session state was rolled back (activeTurnId is null); if it persists, recreate the session.
Example fix
// before (naive caller)
const { turnId } = await session.startTurn({ message });
// after
try {
const { turnId } = await session.startTurn({ message });
} catch (e) {
if (e.message === "Codex turn response omitted turn.id") {
await recreateSessionAndResubmit();
} else throw e;
} Defensive patterns
Strategy: try-catch
Type guard
function turnResponseHasId(response: unknown): response is { turn: { id: string } } {
const r = response as { turn?: { id?: unknown } };
return typeof r?.turn?.id === "string" && r.turn.id.length > 0;
} Try / catch
try {
const { turnId } = await session.startTurn({ message });
} catch (e) {
if (e.message === "Codex turn response omitted turn.id") {
// optimistic state was rolled back by the library; safe to resubmit
// after verifying the app-server version / response shape
await resubmitTurnAfterShapeCheck();
} else throw e;
} Prevention
- Pin and smoke-test the Codex app-server version against expected turn/start response shape before upgrading.
- Log raw turn/start responses in staging to catch shape drift early.
- Ensure no proxy/middleware between runner and app-server mutates RPC payloads.
When it happens
Trigger: The turn/start RPC resolves successfully but its response payload has no turn object or turn.id is an empty/non-string value — e.g. an app-server version returning a different response shape, a proxy stripping fields, or the provider rejecting the turn without a JSON-RPC error.
Common situations: Upgrading or downgrading the Codex app-server so turn/start's response schema changed; running against a mock or misconfigured transport; provider-side rejection surfaced as a success-shaped empty response instead of a protocol error.
Related errors
- Codex thread response omitted thread.id
- provider_initialize_protocol_error
- Codex turn identity changed during start
- Codex turn response omitted turn.id
- device-login promotion: the account identifier cannot form a
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/4cfb47c1450792ac.
Report an issue: GitHub.