{"record":{"id":"151d4483dcae97ea","repo":"paperclipai/paperclip","slug":"native-runner-authority-archive-conflict","errorCode":"native_runner_authority_archive_conflict","errorMessage":"native_runner_authority_archive_conflict","messagePattern":"native_runner_authority_archive_conflict","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/live/runnerd-codex-transport.ts","lineNumber":332,"sourceCode":"    throw new Error(\"native_runner_authority_rotation_requires_settled_state\");\n  }\n  const archivesRoot = resolve(root, \"authority-epochs\");\n  if (existsSync(archivesRoot)) {\n    assertRealDirectory(archivesRoot);\n  } else {\n    mkdirSync(archivesRoot, { mode: 0o700 });\n  }\n  if (existsSync(archive)) {\n    assertRealDirectory(archive);\n  } else {\n    mkdirSync(archive, { mode: 0o700 });\n  }\n  assertRealDirectory(archive);\n  const activeControlPlane = resolve(root, \"control-plane\");\n  if (existsSync(activeControlPlane)) {\n    assertRealDirectory(activeControlPlane);\n    if (existsSync(archivedControlPlane)) {\n      throw new Error(\"native_runner_authority_archive_conflict\");\n    }\n    renameSync(activeControlPlane, archivedControlPlane);\n  }\n  if (existsSync(runnerStatePath)) {\n    if (existsSync(archivedRunnerState)) {\n      throw new Error(\"native_runner_authority_archive_conflict\");\n    }\n    renameSync(runnerStatePath, archivedRunnerState);\n  }\n  if (!existsSync(archivedControlPlane) || !existsSync(archivedRunnerState)) {\n    throw new Error(\"native_runner_authority_archive_incomplete\");\n  }\n  return controlPlaneState;\n}\n\nasync function rotateExternalAuthorityEpoch(\n  root: string,\n  controlPlaneState: Record<string, unknown>,","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/live/runnerd-codex-transport.ts#L314-L350","documentation":"During local authority epoch rotation, the live control-plane directory and runner-state.json are moved (rename) into the newly created epoch archive. If the destination already exists in the archive — meaning an archive entry for these paths is already present — the rotation would clobber a prior archived epoch, so it throws native_runner_authority_archive_conflict. This is a double-rotation / non-idempotent-retry guard.","triggerScenarios":"rotateLocalAuthorityEpoch() runs when archivedControlPlane or archivedRunnerState already exists inside the epoch archive while the corresponding live files also exist (retry after a partially completed rotation, or two rotations racing).","commonSituations":"A previous rotation crashed after creating the archive entry but before clearing live state, then the resume retries rotation; two runner processes resuming the same state root concurrently; operator re-ran rotation manually between attempts.","solutions":["Check the authority-epochs archive: if the prior rotation completed, do not rotate again — resume normally","If a prior rotation died midway, reconcile manually: either move the live control-plane/runner-state into the archive yourself or restore a consistent layout, then resume","Serialize resume/rotation so only one process rotates a given state root at a time (use a lock file)","If archives are stale duplicates, move them aside before retrying, keeping exactly one archive per epoch"],"exampleFix":"// before\nfind data/runner-state/authority-epochs -maxdepth 2   # shows duplicate control-plane entries\n// after\nmv data/runner-state/authority-epochs/<epoch>/control-plane data/runner-state/authority-epochs/<epoch>/control-plane.conflict-<date>\n# reconcile both copies, ensure only one archive entry per epoch, then resume","handlingStrategy":"try-catch","validationCode":"import { existsSync } from \"node:fs\";\nfunction archiveConflictFree(archive: string): boolean {\n  return !existsSync(`${archive}/control-plane`) && !existsSync(`${archive}/runner-state.json`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await transport.resume();\n} catch (err) {\n  if (err.code === \"native_runner_authority_archive_conflict\") {\n    logger.error(\"epoch archive already populated; prior rotation partially completed\");\n    reconcileArchiveThenResume();\n  } else throw err;\n}","preventionTips":["Use a lock so only one process rotates/resumes a state root at a time","After a mid-rotation crash, reconcile the archive before retrying resume","Never run rotation manually while the runner owns the state root","Keep exactly one archive entry per epoch; move duplicates aside after inspection"],"tags":["authority-rotation","filesystem","conflict","codex"],"backgroundTag":"file-already-exists","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"}