paperclipai/paperclip · error
native_runner_warm_transition_completion_unproven
Error message
native_runner_warm_transition_completion_unproven
What it means
Thrown after a `session.snapshot` PRP command completes during warm recovery, when the snapshot fails to prove the native runner's warm transition completed. The transport checks that the resolved provider identity matches the expected driver session id and provider session id, and that `result.status` is one of `prepared`, `session_open`, or `turn_active`. Any mismatch means the warm transition cannot be confirmed.
Source
Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:5483
const expectation = this.#checkpointProviderIdentityExpectation;
const providerIdentity = resolveRunnerdSessionIdentity(result);
if (
command.type !== "session.snapshot" ||
core.store.state.warmTransition !== undefined ||
!recoveryIdentityMatches(
core.store.state.identity,
completion.identity,
) ||
core.store.state.completedWarmTransition?.receipt.transitionId !==
completion.transitionId ||
expectation === null ||
providerIdentity.threadId !== expectation.driverSessionId ||
providerIdentity.sessionId !== expectation.providerSessionId ||
!["prepared", "session_open", "turn_active"].includes(
String(result.status),
)
) {
throw new Error("native_runner_warm_transition_completion_unproven");
}
this.#confirmCheckpointProviderIdentity(
result,
"fresh post-activation session.snapshot",
);
// This newly queued command completed only after runner consumed the
// final activation ACK. Callback failure retains the completion gate;
// retry observes a fresh snapshot, never repeats a provider turn.
const completing = (this.#warmRecoveryCompletionInFlight ??=
Promise.resolve().then(() =>
this.options.onWarmTransitionRecoveryCompleted?.({
transitionId: completion.transitionId,
}),
));
try {
await completing;
if (this.#pendingWarmRecoveryCompletion === completion) {
this.#pendingWarmRecoveryCompletion = null;View on GitHub (pinned to 01ad858492)
Solutions
- Re-run warm recovery from a fresh checkpoint so expectations match the current provider session identity.
- Verify runnerd was not restarted between checkpoint capture and recovery; if it was, cold-start instead of warm-starting.
- Inspect the snapshot `status` — if it is still initializing, retry after the session reaches `prepared`/`session_open`/`turn_active`.
- Check that `resolveRunnerdSessionIdentity` matches the snapshot shape emitted by your runnerd version.
Example fix
// before
if (providerIdentity.threadId !== expectation.driverSessionId ||
providerIdentity.sessionId !== expectation.providerSessionId) {
throw new Error("native_runner_warm_transition_completion_unproven");
}
// after
if (providerIdentity.threadId !== expectation.driverSessionId ||
providerIdentity.sessionId !== expectation.providerSessionId) {
logger.warn({ expected: expectation, got: providerIdentity }, "warm transition identity mismatch; invalidating checkpoint");
await this.#invalidateCheckpoint();
throw new Error("native_runner_warm_transition_completion_unproven");
} Defensive patterns
Strategy: validation
Validate before calling
const identity = resolveRunnerdSessionIdentity(snapshot);
if (identity.threadId !== expectation.driverSessionId || identity.sessionId !== expectation.providerSessionId) {
invalidateCheckpoint();
} Type guard
function isWarmTransitionSnapshot(result) {
return ["prepared", "session_open", "turn_active"].includes(result?.status);
} Try / catch
try {
await warmRecover(checkpoint);
} catch (err) {
if (err.message === "native_runner_warm_transition_completion_unproven") {
await coldStart(); // fall back to a fresh session
} else throw err;
} Prevention
- Invalidate checkpoints whenever runnerd restarts.
- Verify snapshot status before asserting warm completion.
- Keep session identity expectations in sync with the live provider session.
When it happens
Trigger: Warm recovery path queues a `session.snapshot` command with a pending warm-recovery completion, then `resolveRunnerdSessionIdentity(result)` yields a threadId/sessionId that differs from `expectation.driverSessionId`/`expectation.providerSessionId`, or the snapshot `status` is outside the accepted set.
Common situations: Stale checkpoint expectations after the provider session was recreated; runnerd restarted into a fresh session so the old session IDs no longer match; snapshot taken too early (status like `idle`/`initializing`); session identity resolution parsing a differently shaped snapshot.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- runnerd digest mismatch: expected ${request.runnerd.sha256},
- provider_initialize_protocol_error
- provider_initialize_protocol_error
- workflow eval delegation checkpoint is missing
- runnerd did not report the provider turn identity
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/f86360b88d9c90e9.
Report an issue: GitHub.