{"record":{"id":"321c0a24f20b5e3d","repo":"paperclipai/paperclip","slug":"acpx-provider-dependency-ancestry-is-invalid","errorCode":null,"errorMessage":"ACPX provider dependency ancestry is invalid","messagePattern":"ACPX provider dependency ancestry is invalid","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts","lineNumber":141,"sourceCode":"const owner = fs.createReadStream(\"\", { fd: 3, autoClose: false });\nowner.once(\"end\", reap);\nowner.once(\"error\", reap);\nowner.resume();\ntry {\n  fs.writeSync(4, \"armed\\\\n\");\n} catch {\n  reap();\n}\n`;\n\nexport const PROVIDER_LIFETIME_GUARDIAN_SOURCE = `\nconst fs = require(\"node:fs\");\nconst { spawn } = require(\"node:child_process\");\nconst WATCHDOG_SOURCE = ${JSON.stringify(PROVIDER_LIFETIME_WATCHDOG_SOURCE)};\nconst runtimeExecutable = process.env.${VERIFIED_RUNTIME_EXECUTABLE_ENV} || process.execPath;\nconst dependencyAncestorCount = Number.parseInt(process.argv[4], 10);\nconst providerRuntimeExecutableCount = Number.parseInt(process.argv[8], 10);\nif (!Number.isSafeInteger(dependencyAncestorCount) || dependencyAncestorCount < 0 || dependencyAncestorCount > ${MAX_DEPENDENCY_ANCESTORS}) throw new Error(\"ACPX provider dependency ancestry is invalid\");\nif (providerRuntimeExecutableCount !== 0 && providerRuntimeExecutableCount !== 1) throw new Error(\"ACPX provider runtime executable count is invalid\");\nconst PROVIDER_RUNTIME_EXECUTABLE_FD = ${DEPENDENCY_ANCESTOR_FD_START} + dependencyAncestorCount;\nconst OWNER_FD = PROVIDER_RUNTIME_EXECUTABLE_FD + providerRuntimeExecutableCount;\nconst OWNERSHIP_FD = OWNER_FD + 1;\nconst PROVIDER_EXIT_FD = OWNERSHIP_FD + 1;\nconst CREDENTIAL_FENCE_FD_START = PROVIDER_EXIT_FD + 1;\nconst VERIFIED_RUNTIME_FD = CREDENTIAL_FENCE_FD_START + 2;\nconst dependencyAncestorFds = Array.from({ length: dependencyAncestorCount }, (_, index) => ${DEPENDENCY_ANCESTOR_FD_START} + index);\nconst runtimeDescriptorMatch = /^\\\\/proc\\\\/self\\\\/fd\\\\/([0-9]+)$/.exec(runtimeExecutable);\nconst runtimeDescriptorFd = runtimeDescriptorMatch === null ? null : Number.parseInt(runtimeDescriptorMatch[1], 10);\nif (runtimeDescriptorFd !== null && runtimeDescriptorFd !== VERIFIED_RUNTIME_FD) throw new Error(\"ACPX verified runtime descriptor is misplaced\");\nif (runtimeDescriptorFd !== null) fs.fstatSync(runtimeDescriptorFd);\nlet provider;\nlet watchdog;\nlet reaped = false;\nlet shutdownStarted = false;\nconst reap = () => {\n  if (reaped) return;","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts#L123-L159","documentation":"This error is thrown inside the generated provider-lifetime watchdog script (a template-literal-generated Node script in installation-integrity.ts). Before spawning, the watchdog parses process.argv[4] as dependencyAncestorCount and validates it is a safe, non-negative integer not exceeding MAX_DEPENDENCY_ANCESTORS. An invalid value means the file-descriptor layout (PROVIDER_RUNTIME_EXECUTABLE_FD, OWNER_FD, etc.) cannot be computed safely, so the watchdog aborts.","triggerScenarios":"The parent (installation-integrity code) passes a malformed or out-of-range argv[4] to the watchdog child process: non-numeric string, NaN, negative number, or a count greater than MAX_DEPENDENCY_ANCESTORS. This can happen if the computed dependency ancestor list grew beyond the cap or a variable interpolation in the spawning code passed the wrong argument position.","commonSituations":"A deeply nested dependency tree exceeding MAX_DEPENDENCY_ANCESTORS after an install changed; refactoring the spawn argv ordering so argv[4] now receives a different value; an environment where the ancestors array is empty/malformed and String(...) yields 'undefined', which parseInt turns into NaN.","solutions":["Inspect the spawn call that launches the watchdog and confirm argv[4] receives the dependency-ancestor count as a decimal string within [0, MAX_DEPENDENCY_ANCESTORS].","If the real dependency ancestry exceeds MAX_DEPENDENCY_ANCESTORS, raise the constant (and DEPENDENCY_ANCESTOR_FD_START layout accordingly) or trim the ancestor set.","Guard the parent side: Number.isSafeInteger(count) && count >= 0 && count <= MAX_DEPENDENCY_ANCESTORS before spawning.","Verify no recent refactor shifted the argv positions consumed by the generated script."],"exampleFix":"// before: count possibly undefined/NaN\nspawn(process.execPath, [watchdogEntry, ..., String(ancestors?.length), ...]);\n\n// after: validate before spawn\nconst count = ancestors?.length ?? 0;\nif (!Number.isSafeInteger(count) || count < 0 || count > MAX_DEPENDENCY_ANCESTORS) {\n  throw new Error(`dependency ancestor count out of range: ${count}`);\n}\nspawn(process.execPath, [watchdogEntry, ..., String(count), ...]);","handlingStrategy":"validation","validationCode":"const count = ancestors?.length ?? 0;\nif (!Number.isSafeInteger(count) || count < 0 || count > MAX_DEPENDENCY_ANCESTORS) {\n  throw new Error(`dependency ancestor count out of range: ${count}`);\n}\n// then pass String(count) at the argv position the watchdog expects","typeGuard":null,"tryCatchPattern":"try {\n  await spawnProviderWatchdog(args);\n} catch (err) {\n  if (err.message.includes('dependency ancestry is invalid')) {\n    // recompute/trim ancestry or raise MAX_DEPENDENCY_ANCESTORS, then retry once\n    args[4] = String(Math.min(ancestors.length, MAX_DEPENDENCY_ANCESTORS));\n    await spawnProviderWatchdog(args);\n  } else throw err;\n}","preventionTips":["Always derive argv values with String(Number.isSafeInteger(n) ? n : 0) before spawning the generated script.","Assert argument count and positions in a unit test that runs the watchdog script with sample argv.","Keep MAX_DEPENDENCY_ANCESTORS in sync with realistic dependency depths; update both sides together."],"tags":["watchdog","argv","validation","process-spawn","acpx"],"backgroundTag":"invalid-argument-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}