paperclipai/paperclip · error
native_runner_authority_archive_conflict
native_runner_authority_archive_conflict
Error message
native_runner_authority_archive_conflict
What it means
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.
Source
Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:332
throw new Error("native_runner_authority_rotation_requires_settled_state");
}
const archivesRoot = resolve(root, "authority-epochs");
if (existsSync(archivesRoot)) {
assertRealDirectory(archivesRoot);
} else {
mkdirSync(archivesRoot, { mode: 0o700 });
}
if (existsSync(archive)) {
assertRealDirectory(archive);
} else {
mkdirSync(archive, { mode: 0o700 });
}
assertRealDirectory(archive);
const activeControlPlane = resolve(root, "control-plane");
if (existsSync(activeControlPlane)) {
assertRealDirectory(activeControlPlane);
if (existsSync(archivedControlPlane)) {
throw new Error("native_runner_authority_archive_conflict");
}
renameSync(activeControlPlane, archivedControlPlane);
}
if (existsSync(runnerStatePath)) {
if (existsSync(archivedRunnerState)) {
throw new Error("native_runner_authority_archive_conflict");
}
renameSync(runnerStatePath, archivedRunnerState);
}
if (!existsSync(archivedControlPlane) || !existsSync(archivedRunnerState)) {
throw new Error("native_runner_authority_archive_incomplete");
}
return controlPlaneState;
}
async function rotateExternalAuthorityEpoch(
root: string,
controlPlaneState: Record<string, unknown>,View on GitHub (pinned to 01ad858492)
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
Example fix
// before find data/runner-state/authority-epochs -maxdepth 2 # shows duplicate control-plane entries // after mv data/runner-state/authority-epochs/<epoch>/control-plane data/runner-state/authority-epochs/<epoch>/control-plane.conflict-<date> # reconcile both copies, ensure only one archive entry per epoch, then resume
Defensive patterns
Strategy: try-catch
Validate before calling
import { existsSync } from "node:fs";
function archiveConflictFree(archive: string): boolean {
return !existsSync(`${archive}/control-plane`) && !existsSync(`${archive}/runner-state.json`);
} Try / catch
try {
await transport.resume();
} catch (err) {
if (err.code === "native_runner_authority_archive_conflict") {
logger.error("epoch archive already populated; prior rotation partially completed");
reconcileArchiveThenResume();
} else throw err;
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- native_runner_authority_rotation_state_unavailable
- codex auth cache: account_id is not a valid account handle
- codex auth cache: account-home directory no longer exists; r
- Codex working directory must exist before provider admission
- codex_startup_trust_cannot_preserve_configuration
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/151d4483dcae97ea.
Report an issue: GitHub.