paperclipai/paperclip · error
native_runner_warm_transition_completion_pending
native_runner_warm_transition_completion_pending
Error message
native_runner_warm_transition_completion_pending
What it means
During a warm recovery/transition the transport buffers which methods are safe (thread/read, initialize, collaborationMode/list); any other JSON-RPC method is rejected while #pendingWarmRecoveryCompletion is non-null. This prevents requests from racing the in-progress recovery that re-binds runner state.
Source
Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:3290
diagnostics: ["lab transport selected authenticated durable PRP"],
};
}
evidence(): CapabilityRunnerdProcessEvidence {
return structuredClone(this.#evidence);
}
async request(
method: string,
params: Record<string, unknown>,
): Promise<Record<string, unknown>> {
if (this.#closed) throw new Error("PRP Codex transport is closed");
this.#throwIfFailed();
if (
this.#pendingWarmRecoveryCompletion !== null &&
!["thread/read", "initialize", "collaborationMode/list"].includes(method)
) {
throw new Error("native_runner_warm_transition_completion_pending");
}
if (method === "initialize") return { user: {} };
if (method === "thread/start") return this.#start(params);
if (method === "collaborationMode/list") {
// runnerd negotiates the real Codex preset or the provider-proxy-owned
// planning contract during session.open. This transport-level mask
// confirms that closed boundary; turn/start remains runner-managed and
// never forwards this sentinel to the outer TypeScript driver.
return this.options.provider === undefined ||
this.options.provider === "codex" ||
this.options.provider === "opencode" ||
this.options.provider === "acpx"
? {
data: [
{
name: "Plan",
mode: "plan",
model: "runner-managed",View on GitHub (pinned to 01ad858492)
Solutions
- Wait for warm-recovery completion before sending turn/start or other non-read methods (poll thread/read or listen for the completion signal).
- Restrict the reconnection handshake to initialize / thread/read / collaborationMode/list until recovery completes.
- Retry the rejected method with backoff after the pending completion clears.
- If recovery appears stuck, investigate the recovery path rather than forcing requests.
Example fix
// before
await transport.request('thread/turns/start', params); // may throw during recovery
// after
await transport.waitForWarmRecoveryCompletion();
await transport.request('thread/turns/start', params); Defensive patterns
Strategy: retry
Validate before calling
// no direct predicate exposed; probe with an allowed method first
await transport.request('thread/read', { threadId }); // permitted during warm recovery Try / catch
try {
await transport.request('thread/turns/start', params);
} catch (err) {
if ((err as Error).message === 'native_runner_warm_transition_completion_pending') {
await waitForWarmRecovery(transport); // poll thread/read or completion signal
await transport.request('thread/turns/start', params);
} else throw err;
} Prevention
- Serialize reconnection: finish handshake (initialize/thread/read) before turn calls
- Back off and retry turn methods on this error
- Surface warm-recovery state in UI so clients wait
When it happens
Trigger: Calling request() with any method other than thread/read, initialize, or collaborationMode/list (e.g. thread/start, turn/step) while a warm recovery completion is still pending.
Common situations: Client reconnect issuing turn requests immediately after warm attach; automation firing turn/start before recovery finalizes; a long recovery overlapping normal traffic.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- provider_checkpoint_failed_terminal
- provider turn ended with status ${turn.status}
- Plugin UI is not available (status: ${plugin.status})
- Plugin is not ready (current status: ${plugin.status})
- ${message}
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/00c845340d1d4c34.
Report an issue: GitHub.