paperclipai/paperclip · error
Warm run transition target conflicts with its durable receip
Error message
Warm run transition target conflicts with its durable receipt.
What it means
rotateRunIdentity() was called with an identity whose canonical JSON does not equal the newIdentity recorded in the durable warm transition receipt. The transition receipt is the authoritative record of the target identity, so any mismatched rotation attempt is rejected to prevent hijacking the transition to a different identity.
Source
Thrown at packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts:1643
if (
runAttachTemplate !== undefined &&
canonicalJson(runAttachTemplate) !== canonicalJson(template)
) {
throw new Error(
"Completed warm transition template conflicts with its exact command.",
);
}
return;
}
const transition = this.#store.state.warmTransition;
if (transition) {
if (transition.phase === "awaiting_result")
throw new Error("Warm transition result is not yet authenticated.");
if (
canonicalJson(identity) !==
canonicalJson(transition.receipt.newIdentity)
) {
throw new Error(
"Warm run transition target conflicts with its durable receipt.",
);
}
// The new authenticated peer, not an attach-result observer, owns the
// activation boundary. Keep the old credential and command replay lane.
if (runAttachTemplate !== undefined) {
const { paperclipNextAuthority: _boundary, ...expectedTemplate } =
transition.command.payload;
if (
canonicalJson(runAttachTemplate) !== canonicalJson(expectedTemplate)
) {
throw new Error(
"Warm run transition template conflicts with its exact command.",
);
}
const candidate = structuredClone(this.#store.state);
candidate.runAttachTemplate = structuredClone(runAttachTemplate);
this.#store.commit(candidate);View on GitHub (pinned to 01ad858492)
Solutions
- Use exactly the identity from warmTransition.receipt.newIdentity when calling rotateRunIdentity during a transition.
- If a different target identity is truly wanted, cancel/reset the existing transition via the recovery path first.
- Persist and reload the receipt identity rather than recomputing it from local config.
- Log canonicalJson(identity) vs transition.receipt.newIdentity to find the differing field.
Example fix
// before
controlPlane.rotateRunIdentity({ ...newIdentity, runId: freshRunId() }); // conflicts with receipt
// after
const receipt = store.state.warmTransition.receipt;
controlPlane.rotateRunIdentity(structuredClone(receipt.newIdentity)); Defensive patterns
Strategy: validation
Validate before calling
const t = store.state.warmTransition;
if (t && canonicalJson(identity) !== canonicalJson(t.receipt.newIdentity)) {
identity = structuredClone(t.receipt.newIdentity); // adopt receipt identity
} Type guard
function matchesReceipt(identity: DurableRecoveryIdentity, t: { receipt: { newIdentity: DurableRecoveryIdentity } }): boolean {
return canonicalJson(identity) === canonicalJson(t.receipt.newIdentity);
} Try / catch
try {
controlPlane.rotateRunIdentity(identity);
} catch (err) {
if (err instanceof Error && err.message.includes("target conflicts with its durable receipt")) {
controlPlane.rotateRunIdentity(structuredClone(store.state.warmTransition.receipt.newIdentity));
} else throw err;
} Prevention
- Always source the rotation identity from the transition receipt, never from freshly generated ids.
- Persist the target identity at transition initiation and reload it after restarts.
- Ensure only one supervisor issues rotations for a given run.
When it happens
Trigger: Calling rotateRunIdentity(identity) while an authenticated warmTransition exists, passing an identity with different runnerInstanceId, environmentLeaseId, normalizedSessionId, or runId than transition.receipt.newIdentity.
Common situations: The caller regenerated runId between transition initiation and rotation; stale cached identity from a previous process; two supervisors racing with different target identities; config change altered a lease/session id mid-transition.
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
- Completed warm transition template conflicts with its exact
- Warm run transition template conflicts with its exact comman
- Warm transition result is not yet authenticated.
- Warm run identity rotation requires a durable transition rec
- Durable PRP run identity rotation is invalid.
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/b03385c67e8f4673.
Report an issue: GitHub.