paperclipai/paperclip · error

PRP provider resume state is unavailable

Error message

PRP provider resume state is unavailable

What it means

#resume() requires a PRP identity (session/turn/item identifiers) to resume the provider, and this error signals none was supplied. Without the desired identity the transport cannot locate control-plane state or archived state to resume from.

Source

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

            : provider === "claude_managed"
              ? "anthropic"
              : provider === "aws_agentcore"
                ? "aws"
                : provider === "acpx"
                  ? acpxAgent === "pi"
                    ? "openrouter"
                    : acpxAgent === "claude"
                      ? "anthropic"
                      : "openai"
                  : "openai",
      },
    };
  }

  async #resume(): Promise<void> {
    const desiredIdentity = this.options.prpIdentity;
    if (desiredIdentity === undefined) {
      throw new Error("PRP provider resume state is unavailable");
    }
    const controlPlaneDirectory = resolve(this.#root, "control-plane");
    const controlPlaneStatePath = resolve(
      controlPlaneDirectory,
      "control-plane-state.json",
    );
    const localProvider =
      this.options.provider === undefined ||
      this.options.provider === "codex" ||
      this.options.provider === "opencode" ||
      this.options.provider === "acpx";
    const localStateOwner =
      this.options.readRunnerState === undefined &&
      this.options.runnerStateDirectory === undefined &&
      this.options.runnerFilesystemRoot === undefined;
    const localRunnerStatePath = resolve(
      this.#root,
      "runner",

View on GitHub (pinned to 01ad858492)

Solutions

  1. Pass options.prpIdentity when constructing the transport for resumable turns
  2. Only invoke resume() on transports whose options include a PRP identity
  3. Persist and reload the original prpIdentity (sessionId/turnId/itemId) through crash/recovery flows
  4. Check your snapshot/serialization path is not dropping prpIdentity

Example fix

// before
const transport = new RunnerdCodexTransport({ runnerBinary, root });
await transport.resume();
// after
const transport = new RunnerdCodexTransport({ runnerBinary, root, prpIdentity: savedIdentity });
await transport.resume();
Defensive patterns

Strategy: validation

Validate before calling

if (!transport.options.prpIdentity) {
  throw new Error("cannot resume: prpIdentity is required for PRP resume");
}

Type guard

function isResumable(t: RunnerdCodexTransportOptions): t is RunnerdCodexTransportOptions & { prpIdentity: PrpIdentity } {
  return t.prpIdentity !== undefined;
}

Try / catch

try {
  await transport.resume();
} catch (err) {
  if (err instanceof Error && err.message === "PRP provider resume state is unavailable") {
    startFreshTurn(); // fall back to a new turn instead of resuming
  } else throw err;
}

Prevention

When it happens

Trigger: Calling resume() on a transport constructed with options.prpIdentity === undefined — e.g. a transport created for a fresh turn or a non-PRP provider being asked to perform a PRP resume.

Common situations: Recovering a runner after crash without passing the original turn's prpIdentity; wiring a generic transport factory that omits prpIdentity for codex turns; resuming from a stale snapshot where identity was dropped during serialization.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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