paperclipai/paperclip · error

Refusing to activate payload outside

Error message

Refusing to activate payload outside ${paths.installsRoot}.

What it means

assertPayloadPath computed path.relative from the installs root to the payload and got an escaping relative path, so activating it would point 'current' outside the store.

Solutions

  1. Activate only payloads located inside ${paths.installsRoot}.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at cli/src/install-store.ts:250 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at cli/src/install-store.ts:250

export function writeInstallManifestAtomic(
  manifest: InstallManifest,
  paths = resolveInstallStorePaths(),
): void {
  ensurePrivateDirectory(paths.cliRoot);
  const temporaryPath = `${paths.manifestPath}.tmp-${process.pid}-${Date.now()}`;
  try {
    fs.writeFileSync(temporaryPath, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
    fs.renameSync(temporaryPath, paths.manifestPath);
  } finally {
    fs.rmSync(temporaryPath, { force: true });
  }
}

function assertPayloadPath(payloadPath: string, paths: InstallStorePaths): void {
  const relative = path.relative(paths.installsRoot, path.resolve(payloadPath));
  if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) {
    throw new Error(`Refusing to activate payload outside ${paths.installsRoot}.`);
  }
  const stat = fs.lstatSync(payloadPath);
  if (!stat.isDirectory() || stat.isSymbolicLink()) {
    throw new Error(`Refusing to activate non-directory payload ${payloadPath}.`);
  }
  const installsRealPath = fs.realpathSync(paths.installsRoot);
  const payloadRealPath = fs.realpathSync(payloadPath);
  if (!payloadRealPath.startsWith(`${installsRealPath}${path.sep}`)) {
    throw new Error(`Refusing to activate payload that resolves outside ${paths.installsRoot}.`);
  }
}

export function flipCurrentAtomic(
  payloadPath: string,
  paths = resolveInstallStorePaths(),
  hooks: { beforeRename?: () => void } = {},
): void {
  assertPayloadPath(payloadPath, paths);

View on GitHub (pinned to 01ad858492)