paperclipai/paperclip · error · Error

ACPX provider package ancestry is invalid

Error message

ACPX provider package ancestry is invalid

What it means

Child-bootstrap validation of the server's dependency ancestor count (serverDependencyAncestorCount). It must be a safe integer within [0, dependencyAncestorCount] — the server's own ancestry is a prefix of the total ancestry loaded through pinned descriptors. This enforces that the server package's module chain is a consistent subset of the verified chain.

Source

Thrown at packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts:1683

    'const { dirname, extname, join, normalize, relative, resolve } = require("node:path");',
    'const { fileURLToPath, pathToFileURL } = require("node:url");',
    "const commandDirectory = process.argv[1];",
    "const commandName = process.argv[2];",
    "const dependencyAncestorCount = Number.parseInt(process.argv[3], 10);",
    "const serverDependencyAncestorCount = Number.parseInt(process.argv[4], 10);",
    "const serverPackageFormat = process.argv[5];",
    "const dependencyAncestorFormats = JSON.parse(process.argv[6]);",
    "const providerRuntimeExecutableCount = Number.parseInt(process.argv[7], 10);",
    `const providerRuntimeEnvironmentVariable = process.env.${VERIFIED_PROVIDER_RUNTIME_TARGET_ENV};`,
    `delete process.env.${VERIFIED_PROVIDER_RUNTIME_TARGET_ENV};`,
    `const snapshotHandoff = process.platform === "darwin" ? JSON.parse(process.env.${ACPX_PRIVATE_SNAPSHOT_ENV} || "null") : null;`,
    'let privateSnapshot = null; if (snapshotHandoff) { const manifest = fs.readFileSync(snapshotHandoff.path); if (require("node:crypto").createHash("sha256").update(manifest).digest("hex") !== snapshotHandoff.digest) throw new Error("ACPX snapshot manifest digest mismatch"); privateSnapshot = JSON.parse(manifest); }',
    `delete process.env.${ACPX_PRIVATE_SNAPSHOT_ENV};`,
    'if (process.platform !== "linux" && !(process.platform === "darwin" && privateSnapshot && Array.isArray(privateSnapshot.roots) && privateSnapshot.roots.length === dependencyAncestorCount + 1)) throw new Error("ACPX provider requires verified package snapshots");',
    'const verifySnapshotBytes = (path, bytes) => { if (privateSnapshot && require("node:crypto").createHash("sha256").update(bytes).digest("hex") !== privateSnapshot.digests[path]) throw new Error("ACPX private snapshot digest mismatch"); };',
    'if (privateSnapshot && providerRuntimeExecutableCount === 1) verifySnapshotBytes(privateSnapshot.executable, fs.readFileSync(privateSnapshot.executable));',
    `if (!Number.isSafeInteger(dependencyAncestorCount) || dependencyAncestorCount < 0 || dependencyAncestorCount > ${MAX_DEPENDENCY_ANCESTORS}) throw new Error("ACPX provider dependency ancestry is invalid");`,
    'if (!Number.isSafeInteger(serverDependencyAncestorCount) || serverDependencyAncestorCount < 0 || serverDependencyAncestorCount > dependencyAncestorCount) throw new Error("ACPX provider package ancestry is invalid");',
    'if ((serverPackageFormat !== "module" && serverPackageFormat !== "commonjs") || !Array.isArray(dependencyAncestorFormats) || dependencyAncestorFormats.length !== dependencyAncestorCount || dependencyAncestorFormats.some((value) => value !== "module" && value !== "commonjs")) throw new Error("ACPX provider package formats are invalid");',
    'if (providerRuntimeExecutableCount !== 0 && providerRuntimeExecutableCount !== 1) throw new Error("ACPX provider runtime executable count is invalid");',
    `const providerRuntimeExecutableFd = ${DEPENDENCY_ANCESTOR_FD_START} + dependencyAncestorCount;`,
    'if (providerRuntimeExecutableCount === 1) { if (providerRuntimeEnvironmentVariable !== "CODEX_PATH" && providerRuntimeEnvironmentVariable !== "CLAUDE_CODE_EXECUTABLE") throw new Error("ACPX provider runtime environment target is invalid"); fs.fstatSync(providerRuntimeExecutableFd); process.env[providerRuntimeEnvironmentVariable] = privateSnapshot ? privateSnapshot.executable : "/proc/" + process.pid + "/fd/" + providerRuntimeExecutableFd; } else if (providerRuntimeEnvironmentVariable !== undefined) throw new Error("ACPX provider runtime environment target is unexpected");',
    ...(guarded
      ? [
          `const guardianFd = ${DEPENDENCY_ANCESTOR_FD_START} + dependencyAncestorCount + providerRuntimeExecutableCount;`,
          'const guardian = fs.createReadStream("", { fd: guardianFd, autoClose: false });',
          `const reapCurrentProviderProcessGroup = ${reapCurrentProviderProcessGroup.toString()};`,
          "const killProviderProcess = process.kill.bind(process);",
          "const providerProcessId = process.pid;",
          "const exitProviderProcess = process.exit.bind(process);",
          "let guardianLost = false;",
          "const reapOnGuardianLoss = () => { if (guardianLost) return; guardianLost = true; reapCurrentProviderProcessGroup(killProviderProcess, providerProcessId, exitProviderProcess); };",
          'guardian.once("end", reapOnGuardianLoss);',
          'guardian.once("error", reapOnGuardianLoss);',
          "guardian.resume();",
          "fs.fstatSync(guardianFd + 1);",

View on GitHub (pinned to 01ad858492)

Solutions

  1. Use the library's verified spawn() path so serverDependencyAncestorCount and dependencyAncestorCount are derived together.
  2. Verify argument order: total ancestor count comes before server ancestor count in argv.
  3. Rebuild/reinstall the runner if a stale bootstrap is mismatched with the spawning code.
  4. If constructing both counts, assert serverDependencyAncestorCount <= dependencyAncestorCount before spawn.
Defensive patterns

Strategy: validation

Validate before calling

if (!(Number.isSafeInteger(serverDependencyAncestorCount) && serverDependencyAncestorCount >= 0 && serverDependencyAncestorCount <= dependencyAncestors.length)) {
  throw new Error("server ancestor count must be within [0, total ancestor count]");
}

Prevention

When it happens

Trigger: The child receives serverDependencyAncestorCount that is not a safe non-negative integer, or a value greater than the total dependencyAncestorCount.

Common situations: Manually assembling spawn argv with the count arguments swapped; a wrapper reordering arguments; server/dependency ancestry bookkeeping out of sync after reorganizing module resolution; version mismatch between bootstrap script and caller.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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