{"record":{"id":"7481c7f6d6cab799","repo":"paperclipai/paperclip","slug":"warm-run-transition-capability-is-required-before","errorCode":null,"errorMessage":"Warm run transition capability is required before attachment.","messagePattern":"Warm run transition capability is required before attachment\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts","lineNumber":1844,"sourceCode":"        type === \"run.attach\" &&\n        canonicalJson(payload) === canonicalJson(transition.command.payload)\n      )\n        return transition.command;\n      throw new Error(\n        \"Warm run transition permits only its exact cached attachment replay.\",\n      );\n    }\n    if (\n      type === \"run.attach\" &&\n      payload.paperclipNextAuthority !== undefined &&\n      ![...this.#connections].some(\n        (connection) =>\n          connection.secureChannel !== null &&\n          connection.warmTransitionVersion === 1 &&\n          !connection.replayOnly,\n      )\n    ) {\n      throw new Error(\n        \"Warm run transition capability is required before attachment.\",\n      );\n    }\n    if (\n      !commandTypes.has(type) ||\n      (commandId !== undefined &&\n        (commandId.length > 160 || !stableIdPattern.test(commandId)))\n    ) {\n      throw new Error(\"Durable PRP command is invalid.\");\n    }\n    if (commandId !== undefined) {\n      const existing = this.#store.state.commands.find(\n        (candidate) => candidate.commandId === commandId,\n      );\n      if (existing !== undefined) {\n        if (\n          existing.type !== type ||\n          canonicalJson(existing.payload) !== canonicalJson(payload)","sourceCodeStart":1826,"sourceCodeEnd":1862,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts#L1826-L1862","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wait for the connection handshake to complete (secureChannel established) before issuing the attach command.","Verify both sides negotiate warmTransitionVersion 1; upgrade the peer/runner if it reports a different version.","Reconnect or reset the connection if it is marked replayOnly.","Check connection state flags (secureChannel, warmTransitionVersion, replayOnly) before calling attach."],"exampleFix":"// before\nawait connection.send(attachCommand); // sent before handshake finished\n// after\nawait connection.whenHandshakeComplete(); // secureChannel set, warmTransitionVersion === 1, !replayOnly\nawait connection.send(attachCommand);","handlingStrategy":"validation","validationCode":"function canAttach(conn) {\n  return conn.secureChannel !== null && conn.warmTransitionVersion === 1 && !conn.replayOnly;\n}\nif (!canAttach(connection)) await waitForWarmCapability(connection);","typeGuard":"function hasWarmCapability(conn) {\n  return conn.secureChannel !== null && conn.warmTransitionVersion === 1 && conn.replayOnly === false;\n}","tryCatchPattern":"try {\n  await sendAttach();\n} catch (err) {\n  if (err.message.includes(\"capability is required\")) {\n    await renegotiateWarmTransition();\n    await sendAttach();\n  } else throw err;\n}","preventionTips":["Gate attach calls on handshake-complete events, not timers.","Keep runner and control plane versions aligned so warmTransitionVersion negotiates to 1.","Reset replayOnly connections before attempting attachment."],"tags":["handshake","capability","warm-transition"],"backgroundTag":"unsupported-operation","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}