paperclipai/paperclip · error
native_runner_prp_run_rotation_unavailable
Error message
native_runner_prp_run_rotation_unavailable
What it means
attachRun requires both a live runner core and a completed startup sequence. If either is missing (core null or #startupComplete false), the run-rotation machinery is unavailable and this error is thrown.
Source
Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:3612
this.#failureSignal,
]);
}
throw new Error(
`provider_transport_failed: warm runner did not re-authenticate within ${this.options.runnerReconnectGraceMs ?? 5_000}ms`,
);
}
async attachRun(input: {
runId: string;
turnId: string;
itemId: string;
}): Promise<void> {
if (this.#pendingWarmRecoveryCompletion !== null) {
throw new Error("native_runner_warm_transition_completion_pending");
}
const core = this.#core;
if (!core || !this.#startupComplete) {
throw new Error("native_runner_prp_run_rotation_unavailable");
}
await this.#awaitWarmRunAttachmentReady();
const prior = core.store.state.identity;
const desired: DurableRecoveryIdentity = {
...prior,
runId: input.runId,
turnId: input.turnId,
itemId: input.itemId,
};
const registration = this.options.controlPlaneRegistration
? await this.options.controlPlaneRegistration(core, desired)
: null;
const previousRelease = this.#controlPlaneRelease;
let previousReleased = false;
let activationStarted = false;
try {
const connection: RunnerProcessConnection =
registration?.connection ??View on GitHub (pinned to 01ad858492)
Solutions
- Await the transport's startup/ready promise before calling attachRun
- Check startup diagnostics to find why startup never completed
- Restart the transport if the core is gone
- Add a readiness check in calling code before attach
Example fix
// before const transport = new RunnerdCodexTransport(...); await transport.attachRun(input); // after const transport = new RunnerdCodexTransport(...); await transport.whenReady(); await transport.attachRun(input);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!transport.isReady?.()) throw new Error('transport not ready: start transport before attachRun'); Type guard
function isTransportReady(t) {
return typeof t.isReady === 'function' && t.isReady() === true;
} Try / catch
try {
await transport.attachRun(input);
} catch (e) {
if (e.message === 'native_runner_prp_run_rotation_unavailable') {
await transport.whenReady();
await transport.attachRun(input);
} else throw e;
} Prevention
- Await the transport's ready/startup promise before any attach
- Verify startup succeeded (check startupComplete or equivalent) before use
- Do not reuse a stopped/failed transport instance — construct a new one
When it happens
Trigger: Calling attachRun before the transport finished its startup handshake, or after the core was torn down/failure left it unusable.
Common situations: Calling attachRun immediately after constructing the transport without awaiting startup; startup failed earlier (e.g. runner never came up); attach attempted after stop().
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
- native_runner_warm_attachment_not_quiescent
- native_runner_authority_unavailable
- native_runner_warm_attachment_ambiguous: expected one authen
- native_runner_warm_attachment_runner_exited: runner exited b
- provider_transport_failed: warm runner did not re-authentica
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/8afb8011b0d35269.
Report an issue: GitHub.