paperclipai/paperclip · error

native_runner_authority_archive_unsafe

native_runner_authority_archive_unsafe

Error message

native_runner_authority_archive_unsafe

What it means

assertRealDirectory() verifies that a required state-root path (runtime state root, archive directory, control-plane dir, or maintenance state dir) is a real directory and not a symlink, using lstatSync. It throws native_runner_authority_archive_unsafe when the path is missing as a directory, is a symlink, or is a regular file. This prevents authority rotation and quarantine operations from following links or operating on unexpected file types.

Source

Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:213

}

function assertSuspendedRunnerState(
  state: Record<string, unknown>,
  expected: DurableRecoveryIdentity,
): void {
  if (
    state.schema !== "paperclip.runner.durable.state.v1" ||
    !recoveryIdentityMatches(state, expected) ||
    state.lifecycle !== "suspended"
  ) {
    throw new Error("native_runner_authority_rotation_requires_settled_state");
  }
}

function assertRealDirectory(path: string): void {
  const metadata = lstatSync(path);
  if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
    throw new Error("native_runner_authority_archive_unsafe");
  }
}

function quarantineLocalRuntimeState(root: string, reason: unknown): never {
  assertRealDirectory(root);
  const quarantine = resolve(
    dirname(root),
    `${basename(root)}.quarantine-${randomUUID()}`,
  );
  renameSync(root, quarantine);
  mkdirSync(root, { mode: 0o700 });
  const detail = reason instanceof Error ? reason.message : String(reason);
  throw new Error(
    `native_runner_state_quarantined: ${detail}; the prior state was preserved for operator recovery`,
  );
}

function authorityArchiveDirectory(

View on GitHub (pinned to 01ad858492)

Solutions

  1. Run `ls -la` on the configured state root; replace symlinks with real directories (or copy contents into a real directory)
  2. Recreate the missing directory with `mkdir -p` and correct ownership/permissions (0700)
  3. Fix the runner state-root configuration to point at an actual directory
  4. If the layout is unrecoverable, move the directory aside and let the runner re-initialize fresh state

Example fix

// before
PAPERCLIP_RUNNER_STATE_ROOT=~/dotfiles/runner-state  # symlink
// after
mkdir -p ~/var/paperclip/runner-state && cp -a ~/dotfiles/runner-state/. ~/var/paperclip/runner-state/
PAPERCLIP_RUNNER_STATE_ROOT=~/var/paperclip/runner-state
Defensive patterns

Strategy: validation

Validate before calling

import { lstatSync } from "node:fs";
function isRealDirectory(p: string): boolean {
  try {
    const m = lstatSync(p);
    return m.isDirectory();
  } catch { return false; }
}

Try / catch

try {
  runner.start();
} catch (err) {
  if (err.code === "native_runner_authority_archive_unsafe") {
    logger.error("state root is not a real directory (symlink/file/missing)", { path });
    recreateStateRoot();
  } else throw err;
}

Prevention

When it happens

Trigger: quarantineLocalRuntimeState, latestArchivedControlPlaneState, rotateLocalAuthorityEpoch, rotateExternalAuthorityEpoch, or readMaintenanceState is given a path that is a symlink, a plain file, or not a directory at all.

Common situations: State root configured to a symlinked path (common with dotfile managers or mounted volumes); someone replaced the state directory with a file; the directory was deleted while the runner was down; tmpfs/bind-mount layouts in containers.

Related errors


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