paperclipai/paperclip · error

Warm run transition capability is required before attachment

Error message

Warm run transition capability is required before attachment.

What it means

Before an attachment command is accepted, the control plane checks that the connection has completed the warm-transition handshake: an established secure channel, warmTransitionVersion === 1, and not being replay-only. If the connection has not negotiated this capability, attaching is rejected because warm transition attachment requires the prior capability handshake.

Source

Thrown at packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts:1844

        type === "run.attach" &&
        canonicalJson(payload) === canonicalJson(transition.command.payload)
      )
        return transition.command;
      throw new Error(
        "Warm run transition permits only its exact cached attachment replay.",
      );
    }
    if (
      type === "run.attach" &&
      payload.paperclipNextAuthority !== undefined &&
      ![...this.#connections].some(
        (connection) =>
          connection.secureChannel !== null &&
          connection.warmTransitionVersion === 1 &&
          !connection.replayOnly,
      )
    ) {
      throw new Error(
        "Warm run transition capability is required before attachment.",
      );
    }
    if (
      !commandTypes.has(type) ||
      (commandId !== undefined &&
        (commandId.length > 160 || !stableIdPattern.test(commandId)))
    ) {
      throw new Error("Durable PRP command is invalid.");
    }
    if (commandId !== undefined) {
      const existing = this.#store.state.commands.find(
        (candidate) => candidate.commandId === commandId,
      );
      if (existing !== undefined) {
        if (
          existing.type !== type ||
          canonicalJson(existing.payload) !== canonicalJson(payload)

View on GitHub (pinned to 01ad858492)

Solutions

  1. Wait for the connection handshake to complete (secureChannel established) before issuing the attach command.
  2. Verify both sides negotiate warmTransitionVersion 1; upgrade the peer/runner if it reports a different version.
  3. Reconnect or reset the connection if it is marked replayOnly.
  4. Check connection state flags (secureChannel, warmTransitionVersion, replayOnly) before calling attach.

Example fix

// before
await connection.send(attachCommand); // sent before handshake finished
// after
await connection.whenHandshakeComplete(); // secureChannel set, warmTransitionVersion === 1, !replayOnly
await connection.send(attachCommand);
Defensive patterns

Strategy: validation

Validate before calling

function canAttach(conn) {
  return conn.secureChannel !== null && conn.warmTransitionVersion === 1 && !conn.replayOnly;
}
if (!canAttach(connection)) await waitForWarmCapability(connection);

Type guard

function hasWarmCapability(conn) {
  return conn.secureChannel !== null && conn.warmTransitionVersion === 1 && conn.replayOnly === false;
}

Try / catch

try {
  await sendAttach();
} catch (err) {
  if (err.message.includes("capability is required")) {
    await renegotiateWarmTransition();
    await sendAttach();
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the attach command on a connection whose secureChannel is null (handshake not finished), whose warmTransitionVersion is not 1 (old/new peer version), or which is flagged replayOnly.

Common situations: Attempting attachment before the TLS/secure channel handshake completes; version skew between runner and control plane so warmTransitionVersion stays at 0; connection downgraded to replay-only after a reconnect.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/7481c7f6d6cab799. Report an issue: GitHub.