{"record":{"id":"eb80b58148a63a5b","repo":"paperclipai/paperclip","slug":"runner-provider-package-root-incompatible","errorCode":"runner_provider_package_root_incompatible","errorMessage":"runner_provider_package_root_incompatible: ACPX sidecar must use the provider package dist/cli layout","messagePattern":"runner_provider_package_root_incompatible: ACPX sidecar must use the provider package dist/cli layout","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/live/runnerd-codex-transport.ts","lineNumber":2724,"sourceCode":"  throw new Error(\n    `runner_local_provider_artifact_missing: ${artifact} is absent; build @paperclipai/paperclip-runner TypeScript artifacts with build:typescript before starting a local JS-backed provider`,\n  );\n}\n\nfunction acpxProviderPackageAuthority(\n  sidecarScript: string,\n  ownerPackageRoot = packageRoot,\n): {\n  root: string;\n  manifest: string;\n} {\n  const cliDirectory = dirname(sidecarScript);\n  if (\n    basename(sidecarScript) !== \"acpx-runtime-sidecar.cjs\" ||\n    basename(cliDirectory) !== \"cli\" ||\n    basename(dirname(cliDirectory)) !== \"dist\"\n  ) {\n    throw new Error(\n      \"runner_provider_package_root_incompatible: ACPX sidecar must use the provider package dist/cli layout\",\n    );\n  }\n  const sidecarPackageRoot = resolve(cliDirectory, \"../..\");\n  // A local source build lives at <workspace>/packages/paperclip-runner and\n  // resolves dependencies from <workspace>/node_modules. `pnpm deploy` makes\n  // the package itself the deployment root and owns <deploy>/node_modules/.pnpm.\n  // The older npm-installed portable shape nests the scoped package at\n  // <deploy>/node_modules/@paperclipai/paperclip-runner. The verifier always\n  // receives the directory that owns node_modules, regardless of which\n  // portable shape launched the already-authenticated sidecar.\n  const sourceDependencyRoot = resolve(ownerPackageRoot, \"../..\");\n  const localDependencyRoot = existsSync(\n    resolve(ownerPackageRoot, \"node_modules\", \".pnpm\"),\n  )\n    ? ownerPackageRoot\n    : basename(sourceDependencyRoot) === \"node_modules\"\n      ? resolve(sourceDependencyRoot, \"..\")","sourceCodeStart":2706,"sourceCodeEnd":2742,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/live/runnerd-codex-transport.ts#L2706-L2742","documentation":"acpxProviderPackageAuthority validates that the ACPX sidecar script path follows the strict provider-package layout <packageRoot>/dist/cli/acpx-runtime-sidecar.cjs. Anything else (source-tree script, renamed file, relocated install) is rejected because the code resolves the package root and dependency layout from that structure.","triggerScenarios":"Passing a sidecarScript whose basename is not acpx-runtime-sidecar.cjs, whose parent directory is not named 'cli', or whose grandparent is not named 'dist' when constructing the ACPX provider transport.","commonSituations":"Pointing the sidecar at a source .ts/.cjs file during dev; a custom packaging step that emits to a different directory; symlinked or pnpm-store paths breaking the dist/cli shape; hand-copying the sidecar script elsewhere.","solutions":["Use the sidecar script at <providerPackageRoot>/dist/cli/acpx-runtime-sidecar.cjs exactly.","Rebuild/redeploy the provider package (pnpm build / pnpm deploy) so the dist/cli layout exists.","Do not rename or relocate the sidecar script; if packaging differs, restore the dist/cli directory structure.","If resolving from a workspace, ensure resolution goes through node_modules to the deployed package, not the raw source path."],"exampleFix":"// before\nconst sidecar = 'packages/acpx/src/acpx-runtime-sidecar.cjs';\n// after\nconst sidecar = require.resolve('acpx-provider/dist/cli/acpx-runtime-sidecar.cjs');","handlingStrategy":"validation","validationCode":"import { basename, dirname } from 'node:path';\nconst ok = basename(sidecar) === 'acpx-runtime-sidecar.cjs'\n  && basename(dirname(sidecar)) === 'cli'\n  && basename(dirname(dirname(sidecar))) === 'dist';\nif (!ok) throw new Error('sidecar must live at <pkgRoot>/dist/cli/acpx-runtime-sidecar.cjs');","typeGuard":"const isDistCliSidecar = (p: string): boolean =>\n  basename(p) === 'acpx-runtime-sidecar.cjs' && basename(dirname(p)) === 'cli' && basename(dirname(dirname(p))) === 'dist';","tryCatchPattern":"try {\n  acpxProviderPackageAuthority(sidecar);\n} catch (err) {\n  if ((err as Error).message.includes('runner_provider_package_root_incompatible')) {\n    sidecar = require.resolve('acpx-provider/dist/cli/acpx-runtime-sidecar.cjs');\n  } else throw err;\n}","preventionTips":["Always resolve the sidecar with require.resolve, never relative paths","Do not rename or copy the sidecar script out of dist/cli","Validate packaging output in CI matches dist/cli layout"],"tags":["path","validation","acpx","packaging"],"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-14T05:17:10.506Z"}