paperclipai/paperclip · error

runnerd did not report the provider turn identity

Error message

runnerd did not report the provider turn identity

What it means

Thrown by the runnerd Codex transport's warm-start admission path after a polling loop that waits for runnerd to report the provider turn identity. The loop breaks early when `providerTurnStarted()` returns true, throws if the runner process has exited, and sleeps 10ms per iteration. If the loop exhausts without the identity being reported, the transport cannot safely return a `{ turn: { id, status: "inProgress" } }` result, so it aborts the turn start.

Source

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

          ? Date.now() + 30_000
          : commandDeadline;
      const providerTurnStarted = () =>
        turnStartResponseReady({
          responseEpoch,
          observedEpoch: this.#observedTurnStartEpoch,
          expectedProviderTurnId,
          boundTurnId: this.#turnId,
        });
      while (!providerTurnStarted() && Date.now() < deadline) {
        this.#throwIfFailed();
        this.#pumpEvents();
        if (providerTurnStarted()) break;
        if (await this.#runnerHasExited())
          throw new Error("runnerd exited before provider turn startup");
        await new Promise((resolveWait) => setTimeout(resolveWait, 10));
      }
      if (!providerTurnStarted())
        throw new Error("runnerd did not report the provider turn identity");
      responseReady = true;
      return { turn: { id: this.#turnId, status: "inProgress" } };
    } finally {
      if (!responseReady) {
        resolveAdmission(false);
        if (this.#turnStartResponseEpoch === responseEpoch) {
          this.#turnStartResponsePending = false;
          this.#expectedProviderTurnId = null;
        }
      } else {
        // Resolving this async method schedules the strict driver's response
        // continuation as a microtask. Keep terminal frames held until the
        // following task so the driver can bind and emit turn.accepted first.
        // The epoch prevents a late release from clearing a newer turn fence.
        const release = setTimeout(() => {
          resolveAdmission(
            !this.#closed && this.#turnStartResponseEpoch === responseEpoch,
          );

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check runnerd logs to see whether it started the provider turn at all; restart runnerd if it hung before emitting the identity.
  2. Verify runnerd and the paperclip-runner package are version-matched so the provider turn identity event is emitted in the expected form.
  3. Retry the turn start; transient startup slowness resolves on a fresh attempt.
  4. If reproducible, capture the provider identity event stream and file a bug with the runnerd startup logs.

Example fix

// before
if (!providerTurnStarted())
  throw new Error("runnerd did not report the provider turn identity");
// after
if (!providerTurnStarted()) {
  logger.warn("provider turn identity missing; retrying turn start");
  await restartRunnerd();
  throw new Error("runnerd did not report the provider turn identity");
}
Defensive patterns

Strategy: retry

Validate before calling

if (!transport.isProviderThreadReady()) await waitFor(() => transport.isProviderThreadReady(), { timeoutMs: 30_000 });

Try / catch

try {
  await transport.startTurn(input);
} catch (err) {
  if (err.message.includes("provider turn identity")) {
    await backoffRetry(() => transport.startTurn(input), 3);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the transport's turn-start/startSession path while runnerd is slow to publish its provider turn identity (e.g. runnerd still booting, slow snapshot replay, or the identity event never emitted). Also occurs if `providerTurnStarted()`'s underlying evidence (provider identity event/state) never arrives before the poll deadline.

Common situations: Slow or overloaded machine running runnerd; a runnerd build that no longer emits the provider turn identity event; a hung codex subprocess; network/IPC stall between transport and runner; version skew between the transport and runnerd protocol.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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