paperclipai/paperclip · error
Completed warm transition template conflicts with its exact
Error message
Completed warm transition template conflicts with its exact command.
What it means
rotateRunIdentity() was called on a control plane whose warm transition already completed durably (completedWarmTransition is set). For an idempotent replay the caller re-passed a runAttachTemplate whose canonical JSON differs from the template recorded in the completed transition's command payload (after stripping the paperclipNextAuthority boundary field). The library fails closed because the replay does not match the exact original command.
Source
Thrown at packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts:1629
rotateRunIdentity(
identity: DurableRecoveryIdentity,
runAttachTemplate?: Record<string, unknown>,
): void {
if (this.#protocolIntegrityError !== null)
throw this.#protocolIntegrityError;
const completed = this.#store.state.completedWarmTransition;
if (
completed &&
canonicalJson(identity) === canonicalJson(this.#identity) &&
canonicalJson(identity) === canonicalJson(completed.receipt.newIdentity)
) {
const { paperclipNextAuthority: _boundary, ...template } =
completed.command.payload;
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 theView on GitHub (pinned to 01ad858492)
Solutions
- Do not pass runAttachTemplate on idempotent replays of a completed warm transition; call rotateRunIdentity(identity) with the template omitted.
- Compare your template against the completed transition's command payload (minus paperclipNextAuthority) and reuse the exact original object.
- If the template genuinely must change, treat it as a new rotation: reset the transition state per your recovery procedure instead of replaying the completed one.
- Log canonicalJson(runAttachTemplate) and the completed command payload to identify which field drifted before retrying.
Example fix
// before
controlPlane.rotateRunIdentity(newIdentity, { provider: { name: "claude" }, model: "opus" }); // replay after completion, template drifted
// after
controlPlane.rotateRunIdentity(newIdentity); // idempotent replay without re-asserting the template Defensive patterns
Strategy: try-catch
Validate before calling
// before replaying a completed transition
const completed = store.state.completedWarmTransition;
if (completed && runAttachTemplate !== undefined) {
const { paperclipNextAuthority: _b, ...expected } = completed.command.payload;
if (canonicalJson(runAttachTemplate) !== canonicalJson(expected)) {
runAttachTemplate = undefined; // omit on idempotent replay
}
} Try / catch
try {
controlPlane.rotateRunIdentity(identity, runAttachTemplate);
} catch (err) {
if (err instanceof Error && err.message.includes("Completed warm transition template conflicts")) {
controlPlane.rotateRunIdentity(identity); // replay without re-asserting template
} else throw err;
} Prevention
- Omit runAttachTemplate on retries of an already-completed warm transition.
- Keep the template immutable (frozen) once a transition is initiated.
- Strip volatile fields from templates before passing them to rotation.
When it happens
Trigger: Calling rotateRunIdentity(identity, runAttachTemplate) a second time with the same identity after the transition completed, but with a modified runAttachTemplate (different keys, values, ordering-insensitive but content-different) than the one used in the original, already-completed transition.
Common situations: Caller code recomputes the attach template from drifted config (e.g. provider settings changed between retries); a serialization layer adds or drops fields; a retry path passes an updated template while the transition already succeeded on the first attempt.
Related errors
- Warm run transition template conflicts with its exact comman
- Warm run transition target conflicts with its durable receip
- 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/23a3109c2162d0b3.
Report an issue: GitHub.