{"record":{"id":"0867c81a0e88bc35","repo":"paperclipai/paperclip","slug":"acpx-provider-package-name-is-invalid-packagena","errorCode":null,"errorMessage":"ACPX provider package name is invalid: ${packageName}","messagePattern":"ACPX provider package name is invalid: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts","lineNumber":369,"sourceCode":"  issuerPackageJsonPath: string,\n): string {\n  const issuerRequire = createRequire(issuerPackageJsonPath);\n  try {\n    return issuerRequire.resolve(`${packageName}/package.json`);\n  } catch (error) {\n    if (\n      (error as NodeJS.ErrnoException).code !== \"ERR_PACKAGE_PATH_NOT_EXPORTED\"\n    )\n      throw error;\n  }\n\n  const packageSegments = packageName.split(\"/\");\n  if (\n    packageSegments.length < 1 ||\n    packageSegments.length > 2 ||\n    packageSegments.some((segment) => segment.length === 0)\n  ) {\n    throw new Error(`ACPX provider package name is invalid: ${packageName}`);\n  }\n  let directory = dirname(realpathSync(issuerRequire.resolve(packageName)));\n  for (let count = 0; count < MAX_DEPENDENCY_ANCESTORS; count += 1) {\n    const matchesPackage =\n      basename(directory) === packageSegments.at(-1) &&\n      (packageSegments.length === 1 ||\n        basename(dirname(directory)) === packageSegments[0]);\n    if (matchesPackage) return resolve(directory, \"package.json\");\n    const parent = dirname(directory);\n    if (parent === directory) break;\n    directory = parent;\n  }\n  throw new Error(\n    `ACPX provider package manifest could not be located for ${packageName}`,\n  );\n}\n\nfunction pathIsInside(root: string, candidate: string): boolean {","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts#L351-L387","documentation":"When the fast path `issuerRequire.resolve('<pkg>/package.json')` fails with ERR_PACKAGE_PATH_NOT_EXPORTED, resolvePackageJsonFromIssuer falls back to walking ancestor directories of the resolved entry point, splitting the package name on '/'. This error is thrown when the package name is structurally invalid: zero segments, more than two segments (invalid for scoped names), or any empty segment (e.g. leading/trailing slash or '//').","triggerScenarios":"Passing a packageName with an empty segment (`\"@scope/\"`, `\"/pkg\"`, `\"a//b\"`), more than one slash (`\"@a/b/c\"`), or an empty string, to the resolver after the package's package.json subpath is not exported.","commonSituations":"Config or profile data with a typo'd package name; string interpolation producing a trailing slash; programmatically joined scoped names where the scope was already included once and appended again; URL-derived names containing extra path segments.","solutions":["Trim the package name and reject empty strings before calling the resolver.","Validate with a regex like /^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/ before resolving.","Fix the source string so it has at most one '/' and no empty segments.","Ensure exports in the target package include './package.json' so the fallback (and this validation) is not reached at all."],"exampleFix":"// before\nconst name = `${scope}/${subpath}/`; // \"@acpx/codex/\" -> invalid\nresolver(name, issuer);\n// after\nconst name = `${scope}/${subpath}`;\nif (!/^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)) {\n  throw new Error(`bad package name: ${name}`);\n}\nresolver(name, issuer);","handlingStrategy":"validation","validationCode":"const NAME_RE = /^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/;\nif (typeof packageName !== \"string\" || !NAME_RE.test(packageName)) {\n  throw new Error(`invalid package name: ${packageName}`);\n}","typeGuard":"function isValidPackageName(v: unknown): v is string {\n  return typeof v === \"string\" &&\n    v.split(\"/\").length <= 2 &&\n    v.split(\"/\").every((s) => s.length > 0) &&\n    v.length > 0;\n}","tryCatchPattern":"let manifestPath: string;\ntry {\n  manifestPath = resolver(packageName, issuer);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"package name is invalid\")) {\n    throw new Error(`Fix packageName passed to ACPX resolver: \"${packageName}\"`);\n  }\n  throw err;\n}","preventionTips":["Validate package names against npm naming rules before storing them in profiles/config.","Avoid building package names by string concatenation with paths or URLs.","Trim whitespace and strip leading/trailing slashes from user-supplied names.","Prefer adding a './package.json' export to target packages so the fallback path (and its stricter validation) is bypassed."],"tags":["validation","npm","package-name","input-validation"],"backgroundTag":"invalid-argument-format","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"}