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
- Use the library's verified spawn() path so serverDependencyAncestorCount and dependencyAncestorCount are derived together.
- Verify argument order: total ancestor count comes before server ancestor count in argv.
- Rebuild/reinstall the runner if a stale bootstrap is mismatched with the spawning code.
- 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
- Pass counts in the documented argv order (total first, server second)
- Derive both counts from the same verified ancestry arrays
- Avoid custom spawn wrappers that reorder bootstrap arguments
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
- ACPX provider credential fence is invalid
- ACPX provider runtime executable lease is invalid
- ACPX provider package format is invalid
- The setup-token login session could not start.
- ACPX provider dependency ancestry is invalid
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/db2dbed68aa6829d.
Report an issue: GitHub.