paperclipai/paperclip · error
native_runner_warm_transition_snapshot_mismatch
Error message
native_runner_warm_transition_snapshot_mismatch
What it means
Thrown when the warm-transition snapshot proof cannot be produced: proofWasmRunnerSnapshot returns no proof for the candidate runner state given the expected new identity, runner version, and runner digest. This means the on-disk/remote snapshot does not match what the transition expects to own.
Source
Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:4671
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 =
typeof connection.connectUrl === "string"
? new URL(connection.connectUrl)
: null;
if (
connection.mode !== "connect" ||
endpoint === null ||
endpoint.search ||
endpoint.hash ||
endpoint.username ||
endpoint.password ||
(!this.options.controlPlaneRegistration &&
(endpoint.protocol !== "ws:" ||
endpoint.hostname !== "127.0.0.1" ||
endpoint.pathname !== "/durableRecovery/connect" ||
!endpoint.port))View on GitHub (pinned to 01ad858492)
Solutions
- Re-capture the candidate runner state with the currently approved runner binary
- Verify the runner binary digest/version matches the approved artifact (approvedRunnerArtifact)
- Ensure prpIdentity passed to the transition matches the snapshot's session/turn/item identity
- Re-run the warm transition after the underlying turn state has been re-synced
Example fix
// before
const artifact = approvedRunnerArtifact(localRunnerBinaryPath); // stale binary
const proof = proofWasmRunnerSnapshot({ runnerState: candidateRunnerState, expectedRunnerDigest: artifact.digest });
// after
const artifact = approvedRunnerArtifact(this.options.runnerBinary ?? defaultCapabilityRunnerdBinary());
const freshState = await readRunnerState(root); // re-read state matching the approved binary
const proof = proofWasmRunnerSnapshot({ runnerState: freshState, expectedRunnerDigest: artifact.digest, expectedRunnerVersion: artifact.version }); Defensive patterns
Strategy: retry
Validate before calling
const artifact = approvedRunnerArtifact(runnerBinary);
if (candidateRunnerState.runnerVersion !== artifact.version ||
candidateRunnerState.runnerDigest !== artifact.digest) {
throw new Error("runner state does not match approved artifact; re-capture before transition");
} Type guard
null
Try / catch
try {
await transport.beginWarmTransition();
} catch (err) {
if (err instanceof Error && err.message === "native_runner_warm_transition_snapshot_mismatch") {
await recaptureRunnerState();
await transport.beginWarmTransition();
} else throw err;
} Prevention
- Re-capture runner state immediately before warm transitions
- Pin runner binary versions across controller and runners
- Verify identity fields of the snapshot match prpIdentity before transitioning
When it happens
Trigger: candidateRunnerState is stale or from a different runner binary version/digest than the approved artifact; desiredIdentity (prpIdentity) does not match the snapshot's identity; the runner state file was regenerated or overwritten between capture and proof.
Common situations: Runner binary upgraded between snapshot capture and warm transition; mixed-version fleet where the controller expects one digest but the runner wrote another; resuming a snapshot captured for a different turn/session.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- runnerd digest mismatch: expected ${request.runnerd.sha256},
- paperclip_runner_claude_managed_beta_unqualified
- Materialized OpenCode executable digest mismatch
- Public viewer page differs from the trusted shell
- Public viewer asset differs from trusted build: ${file}
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/281e66cf050f5f5c.
Report an issue: GitHub.