paperclipai/paperclip · error

native_runner_warm_transition_activation_pending

Error message

native_runner_warm_transition_activation_pending

What it means

After issuing the run rotation, the transport waits for the activation phase — the runner to be attached/activated with zero pending connections — polling every 10ms until activationDeadline. If the deadline expires or the runner exits first, activation never happened and this error is thrown.

Source

Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:3685

        void registration.failure.catch((error: unknown) => {
          this.#failTransport(
            error instanceof Error ? error : new Error(String(error)),
          );
        });
      }
      await this.#awaitRegistrationReady(registration?.ready);
      const activationDeadline =
        Date.now() + (this.options.runnerReconnectGraceMs ?? 5_000);
      while (
        !recoveryIdentityMatches(core.store.state.identity, desired) ||
        core.store.state.warmTransition !== undefined ||
        core.activeRunnerConnectionCount() === 0
      ) {
        if (
          Date.now() >= activationDeadline ||
          (await this.#runnerHasExited())
        ) {
          throw new Error("native_runner_warm_transition_activation_pending");
        }
        await new Promise<void>((resolveWait) => setTimeout(resolveWait, 10));
      }
      this.#eventIdentity = structuredClone(desired);
      this.#eventSourceSeq = 0;
      this.#deferredTurnStartEvents = [];
      this.#durableTurnId = desired.turnId;
      await previousRelease?.();
      previousReleased = true;
      this.#controlPlaneRelease = registration?.release ?? null;
    } catch (error) {
      const failure = error instanceof Error ? error : new Error(String(error));
      // The future route is ours from registration onward, including failures
      // in template construction, capability admission, and result waiting.
      // Keep the prior release owned by close until its handoff is confirmed.
      this.#controlPlaneRelease = previousReleased ? null : previousRelease;
      await Promise.resolve()
        .then(() => registration?.release())

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check runner logs for a crash or error during activation
  2. Increase the activation deadline if activation is merely slow
  3. Restart the runner and retry the attach
  4. Verify no deadlock between the transport and runner command queue

Example fix

// before
await transport.attachRun(input); // tight activation deadline
// after
try {
  await transport.attachRun(input);
} catch (e) {
  if (e.message === 'native_runner_warm_transition_activation_pending') {
    await restartRunnerAndReattach(input);
  } else throw e;
}
Defensive patterns

Strategy: retry

Try / catch

try {
  await transport.attachRun(input);
} catch (e) {
  if (e.message === 'native_runner_warm_transition_activation_pending') {
    if (await transport.runnerHasExited?.()) {
      await transport.restartRunner();
    }
    await backoffRetry(() => transport.attachRun(input), { attempts: 2 });
  } else throw e;
}

Prevention

When it happens

Trigger: During attachRun's activation loop: Date.now() >= activationDeadline or #runnerHasExited() is true while core state still shows the transition incomplete / zero active runner connections.

Common situations: Runner too slow to complete activation within the deadline; runner crashed mid-activation; overloaded machine making the 10ms-poll window's deadline too tight.

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/f7bf185ccde3778c. Report an issue: GitHub.