paperclipai/paperclip · error

native_runner_warm_transition_requires_exact_owned_endpoint

Error message

native_runner_warm_transition_requires_exact_owned_endpoint

What it means

Thrown when a native runner warm transition is requested but the transport options do not exactly describe an owned, routed-connect endpoint. A warm transition requires: control-plane state, a candidate runner state, controlPlaneRegistration set with warmTransitionRegistrationMode === "routed_connect", and no adoptExistingRunner option. Anything else is rejected to prevent hijacking or misdirecting a warm handover.

Source

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

      controlPlaneState?.schema ===
        "paperclip.runner.durable.control-plane-state.warm-transition.v1" ||
      hasRunnerWarmBoundary ||
      candidateRunnerState?.warmTransition !== undefined ||
      candidateRunnerState?.schema ===
        "paperclip.runner.durable.state.warm-transition.v1";
    if (hasWarmBoundary) {
      // This lane must precede ordinary archive/identity-rebinding recovery.
      // No malformed or unsupported transition is reinterpreted as legacy.
      if (
        (!localStateOwner && !this.options.readRunnerState) ||
        !localProvider ||
        !controlPlaneState ||
        !candidateRunnerState ||
        (this.options.controlPlaneRegistration !== undefined &&
          this.options.warmTransitionRegistrationMode !== "routed_connect") ||
        this.options.adoptExistingRunner !== undefined
      ) {
        throw new Error(
          "native_runner_warm_transition_requires_exact_owned_endpoint",
        );
      }
      const artifact = approvedRunnerArtifact(
        this.options.runnerBinary ?? defaultCapabilityRunnerdBinary(),
      );
      const proof = inspectWarmRunTransition({
        controlPlaneState,
        runnerState: candidateRunnerState,
        expectedNewIdentity: desiredIdentity,
        expectedRunnerVersion: artifact.version,
        expectedRunnerDigest: artifact.digest,
      });
      if (!proof)
        throw new Error("native_runner_warm_transition_snapshot_mismatch");
      const receipt = proof.receipt;
      const connection = receipt.connection;
      const endpoint =

View on GitHub (pinned to 01ad858492)

Solutions

  1. Set warmTransitionRegistrationMode to "routed_connect" when controlPlaneRegistration is provided
  2. Remove adoptExistingRunner from options when performing a warm transition
  3. Ensure both controlPlaneRegistration and candidate runner state are present before requesting the warm transition
  4. Use the adoption path instead if you intend to attach to an existing runner, not a warm transition

Example fix

// before
const options = { controlPlaneRegistration, warmTransitionRegistrationMode: "adopt", adoptExistingRunner: true };
// after
const options = { controlPlaneRegistration, warmTransitionRegistrationMode: "routed_connect" };
Defensive patterns

Strategy: validation

Validate before calling

const warmReady =
  options.controlPlaneRegistration !== undefined &&
  options.warmTransitionRegistrationMode === "routed_connect" &&
  options.adoptExistingRunner === undefined;
if (!warmReady) throw new Error("options do not satisfy warm-transition requirements");

Type guard

null

Try / catch

try {
  await transport.beginWarmTransition();
} catch (err) {
  if (err instanceof Error && err.message === "native_runner_warm_transition_requires_exact_owned_endpoint") {
    // fix option combination, then retry
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the warm-transition path with: missing controlPlaneState or candidate runner state; controlPlaneRegistration defined while warmTransitionRegistrationMode is not "routed_connect"; or adoptExistingRunner set alongside a warm transition.

Common situations: Mixing adoption options (adoptExistingRunner) with warm-transition options in a shared config object; forgetting to set warmTransitionRegistrationMode after enabling controlPlaneRegistration; upgrading a runner where registration mode defaults changed.

Related errors


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