paperclipai/paperclip · error
Warm transition result is not yet authenticated.
Error message
Warm transition result is not yet authenticated.
What it means
rotateRunIdentity() was invoked while the durable warmTransition exists in phase "awaiting_result", meaning the transition handshake has been issued but its authenticated result (receipt) has not yet been written to the durable store. Identity rotation cannot proceed on an unauthenticated transition, so the call is rejected.
Source
Thrown at packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts:1638
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 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.",View on GitHub (pinned to 01ad858492)
Solutions
- Wait until the warm transition advances past "awaiting_result" (result authenticated durably) before calling rotateRunIdentity.
- Poll store state / listen for the transition-completion event instead of retrying rotation on a fixed timer.
- If the transition is permanently stuck in awaiting_result, use the recovery procedure (bootstrap ticket path) to clear it rather than forcing rotation.
- Guard the call site: only rotate when warmTransition is undefined or its phase is not "awaiting_result".
Example fix
// before
if (state.warmTransition) controlPlane.rotateRunIdentity(identity); // may hit awaiting_result
// after
if (!state.warmTransition || state.warmTransition.phase !== "awaiting_result") {
controlPlane.rotateRunIdentity(identity);
} else {
await waitForTransitionResult();
} Defensive patterns
Strategy: retry
Validate before calling
const t = store.state.warmTransition; const canRotate = !t || t.phase !== "awaiting_result"; if (!canRotate) await waitForTransitionResult();
Type guard
function canRotate(state: { warmTransition?: { phase: string } | null }): boolean {
return !state.warmTransition || state.warmTransition.phase !== "awaiting_result";
} Try / catch
try {
controlPlane.rotateRunIdentity(identity);
} catch (err) {
if (err instanceof Error && err.message.includes("not yet authenticated")) {
await waitForTransitionResult(); // then retry once
controlPlane.rotateRunIdentity(identity);
} else throw err;
} Prevention
- Check warmTransition.phase before every rotation call.
- Drive rotation off the transition-settled event, not fixed timers.
- Add exponential backoff for rotation retries around a transition handshake.
When it happens
Trigger: Calling rotateRunIdentity() between the moment a warm transition was initiated and the moment its result/receipt was durably committed — e.g. a runner or supervisor retries rotation immediately after triggering the transition without waiting for the run.attach acknowledgment to settle.
Common situations: Race between a transition initiator and a rotation retry loop; a crash/restart leaves the transition mid-handshake and the recovery code calls rotateRunIdentity before the peer's result lands; polling logic doesn't check transition.phase first.
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Completed warm transition template conflicts with its exact
- Warm run transition target conflicts with its durable receip
- Warm run transition template conflicts with its exact comman
- Warm run identity rotation requires a durable transition rec
- Warm transition recovery requires its explicit one-use boots
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/ad89f61d3a5dd50e.
Report an issue: GitHub.