paperclipai/paperclip · error

native_runner_warm_attachment_not_quiescent

native_runner_warm_attachment_not_quiescent

Error message

native_runner_warm_attachment_not_quiescent: ${JSON.stringify(lastBlockers)}

What it means

Before rotating runner authority, the transport waits until the warm native runner's state is quiescent, polling blockers every 25ms and requiring 2 consecutive ready probes. If quiescence is never reached, it throws with a JSON dump of the last observed blockers so you can see exactly which state (e.g. in-flight turn, pending command) prevented the transition.

Source

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

        {
          quiesceForWarmAttach: true,
        },
        deadline,
      );
      lastBlockers = snapshot.warmAttachBlockers;
      if (snapshot.warmAttachReady === true) {
        consecutiveReadyProbes += 1;
        // A second barrier prevents a provider frame emitted immediately after
        // its terminal notification from racing the authority rotation. Each
        // snapshot wakes runnerd, polls the provider, and drains the preceding
        // durable event prefix before the next probe.
        if (consecutiveReadyProbes >= 2) return;
      } else {
        consecutiveReadyProbes = 0;
      }
      await new Promise<void>((resolveWait) => setTimeout(resolveWait, 25));
    }
    throw new Error(
      `native_runner_warm_attachment_not_quiescent: ${JSON.stringify(lastBlockers)}`,
    );
  }

  async #awaitWarmRunnerConnection(deadline: number): Promise<void> {
    const core = this.#core;
    if (core === null) throw new Error("native_runner_authority_unavailable");
    let reportedReconnectWait = false;
    while (Date.now() < deadline) {
      this.#throwIfFailed();
      const connectionCount = core.activeRunnerConnectionCount();
      if (connectionCount === 1) {
        if (reportedReconnectWait) {
          this.#diagnostic(
            "warm runner re-authenticated before authority rotation",
          );
        }
        return;

View on GitHub (pinned to 01ad858492)

Solutions

  1. Inspect the JSON blockers in the message to identify which runner state is stuck
  2. Wait for or cancel the in-flight turn/run before attempting authority rotation
  3. Restart the runner process if it is hung and never reaches quiescence
  4. Increase the quiescence wait window if legitimate work simply needs more time

Example fix

// before
await transport.rotateAuthority();
// after
try {
  await transport.rotateAuthority();
} catch (e) {
  if (String(e.message).startsWith('native_runner_warm_attachment_not_quiescent')) {
    const blockers = JSON.parse(e.message.split(': ')[1]);
    logger.warn('rotation deferred, blockers:', blockers);
  } else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

const blockers = transport.getWarmAttachmentBlockers?.();
const ready = blockers && Object.keys(blockers).length === 0;
if (!ready) await waitForQuiescence(transport);

Try / catch

try {
  await transport.rotateAuthority();
} catch (e) {
  if (String(e.message).startsWith('native_runner_warm_attachment_not_quiescent')) {
    const blockers = JSON.parse(e.message.slice(e.message.indexOf(':') + 2));
    await drainBlockers(blockers);
    await transport.rotateAuthority();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the warm-attachment/authority-rotation path while the runner still reports blocking state (active work, pending commands, non-idle turn) when the internal deadline expires.

Common situations: A long-running turn still executing when rotation is attempted; a hung runner that never drains its pending work; debugging output showing blockers like active turn IDs or queued commands in the JSON payload.

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