{"record":{"id":"a59d7722e269bec1","repo":"paperclipai/paperclip","slug":"native-runner-warm-attachment-ambiguous-expected","errorCode":null,"errorMessage":"native_runner_warm_attachment_ambiguous: expected one authenticated runner, found ${connectionCount}","messagePattern":"native_runner_warm_attachment_ambiguous: expected one authenticated runner, found (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/live/runnerd-codex-transport.ts","lineNumber":3577,"sourceCode":"  }\n\n  async #awaitWarmRunnerConnection(deadline: number): Promise<void> {\n    const core = this.#core;\n    if (core === null) throw new Error(\"native_runner_authority_unavailable\");\n    let reportedReconnectWait = false;\n    while (Date.now() < deadline) {\n      this.#throwIfFailed();\n      const connectionCount = core.activeRunnerConnectionCount();\n      if (connectionCount === 1) {\n        if (reportedReconnectWait) {\n          this.#diagnostic(\n            \"warm runner re-authenticated before authority rotation\",\n          );\n        }\n        return;\n      }\n      if (connectionCount > 1) {\n        throw new Error(\n          `native_runner_warm_attachment_ambiguous: expected one authenticated runner, found ${connectionCount}`,\n        );\n      }\n      if (!reportedReconnectWait) {\n        reportedReconnectWait = true;\n        this.#diagnostic(\n          \"warm runner connection interrupted; waiting for re-authentication before authority rotation\",\n        );\n      }\n      if (await this.#runnerHasExited()) {\n        throw new Error(\n          \"native_runner_warm_attachment_runner_exited: runner exited before authority rotation\",\n        );\n      }\n      await Promise.race([\n        new Promise<void>((resolveWait) => setTimeout(resolveWait, 25)),\n        this.#failureSignal,\n      ]);","sourceCodeStart":3559,"sourceCodeEnd":3595,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/live/runnerd-codex-transport.ts#L3559-L3595","documentation":"During warm attachment exactly one authenticated runner connection is expected. If the core reports more than one authenticated runner connection, the transport cannot tell which one holds authority and throws, embedding the observed connection count.","triggerScenarios":"#awaitWarmRunnerConnection polls activeRunnerConnectionCount() and observes >1 while waiting for the old runner to be replaced by the re-authenticated one; duplicate runner processes authenticating during the rotation window.","commonSituations":"Two runner processes launched by accident (stale runner still alive plus a new one); a reconnect race where the old connection hasn't been dropped when the new one authenticates.","solutions":["Kill the stale/duplicate runner process so only one remains","Verify only one runnerd instance is launched per run (check process list / supervision config)","Retry rotation after the old connection has fully torn down","Report a bug if the transport itself is creating duplicate connections"],"exampleFix":"// before\n// rotation attempted immediately after spawn\nspawnRunner();\nawait transport.rotateAuthority();\n// after\nspawnRunner();\nawait waitFor(() => transport.activeRunnerConnectionCount() === 1, { timeout: 5000 });\nawait transport.rotateAuthority();","handlingStrategy":"validation","validationCode":"const count = transport.activeRunnerConnectionCount?.() ?? 0;\nif (count > 1) throw new Error(`duplicate runner connections: ${count}`);","typeGuard":null,"tryCatchPattern":"try {\n  await transport.rotateAuthority();\n} catch (e) {\n  if (String(e.message).startsWith('native_runner_warm_attachment_ambiguous')) {\n    await killDuplicateRunners();\n    await retryRotation();\n  } else throw e;\n}","preventionTips":["Ensure your supervisor launches exactly one runner process per run","Wait for the old runner connection to fully close before spawning a replacement","Monitor activeRunnerConnectionCount and alert on values >1"],"tags":["codex","native-runner","duplicate-connection","warm-attachment"],"backgroundTag":"invalid-state-transition","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"}