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

  1. Wait for warm-recovery completion before sending turn/start or other non-read methods (poll thread/read or listen for the completion signal).
  2. Restrict the reconnection handshake to initialize / thread/read / collaborationMode/list until recovery completes.
  3. Retry the rejected method with backoff after the pending completion clears.
  4. 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

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


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