{"record":{"id":"12414e210e6ab3dd","repo":"JuliusBrussee/caveman","slug":"package-not-found","errorCode":null,"errorMessage":"package not found","messagePattern":"package not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/source-graph.ts","lineNumber":152,"sourceCode":"  if (target === undefined || !target.startsWith(\"./\")) {\n    throw new Error(\"import export not found\");\n  }\n  const packageRoot = dirname(packageJSONPath);\n  const absolute = resolve(packageRoot, target);\n  const relativeTarget = relative(packageRoot, absolute);\n  if (relativeTarget === \"..\" || relativeTarget.startsWith(\"../\") || relativeTarget.startsWith(\"..\\\\\")) {\n    throw new Error(\"package export escapes package root\");\n  }\n  return absolute;\n}\n\nfunction dependencyPackageRoot(specifier: string, importer: string): string {\n  return dirname(resolvePackageJSON(barePackageName(specifier), importer));\n}\n\nfunction resolvePackageJSON(packageName: string, importer: string): string {\n  const packageJSONPath = findPackageJSON(packageName, pathToFileURL(importer));\n  if (packageJSONPath === undefined) throw new Error(\"package not found\");\n  return packageJSONPath;\n}\n\nasync function collectPackageClosure(\n  packageRoot: string,\n  files: Set<string>,\n  visitedRoots: Set<string>,\n): Promise<void> {\n  const canonicalRoot = await realpath(packageRoot);\n  if (visitedRoots.has(canonicalRoot)) return;\n  visitedRoots.add(canonicalRoot);\n  // Resolve dependency edges from the physical package location. pnpm exposes\n  // the project dependency as a symlink, while its private dependency links\n  // live beside the physical package under node_modules/.pnpm.\n  const packageJSONPath = resolve(canonicalRoot, \"package.json\");\n  const packageJSON = JSON.parse(await readFile(packageJSONPath, \"utf8\")) as {\n    dependencies?: Record<string, unknown>;\n    optionalDependencies?: Record<string, unknown>;","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/source-graph.ts#L134-L170","documentation":"resolvePackageJSON walks package.json files up from the importer looking for the named package and throws \"package not found\" when none locates it. This is the resolution step behind bare-import handling in the source graph: before a dependency's closure can be collected, its physical package root must be found. The error usually surfaces as the cause of the more specific caveman build errors.","triggerScenarios":"dependencyPackageRoot() is called for a bare specifier whose package is not present in any node_modules reachable from the importing file.","commonSituations":"Dependency not installed (fresh clone without install), pnpm strict node_modules where an undeclared package is not visible to the importer, or a package.json name mismatch after a rename.","solutions":["Install dependencies (pnpm install) so the package exists in node_modules near the importer.","Declare the package as a direct dependency of the importing package — pnpm's isolated layout hides undeclared packages.","Verify the package name in the specifier matches the installed package's declared name."],"exampleFix":"# before: import \"left-pad\" without declaring it (works only via hoisting)\n\n# after\npnpm add left-pad","handlingStrategy":"validation","validationCode":"import { createRequire } from \"node:module\";\nfunction packageResolvable(pkg: string, importer: string): boolean {\n  try {\n    createRequire(importer).resolve(`${pkg}/package.json`);\n    return true;\n  } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await buildSourceGraph(root);\n} catch (error) {\n  const isPkgMissing = (e: unknown) => e instanceof Error && e.message === \"package not found\";\n  if (isPkgMissing(error) || isPkgMissing((error as Error)?.cause)) {\n    // install the missing package or declare it as a direct dependency\n  } else throw error;\n}","preventionTips":["Declare every imported package as a direct dependency — pnpm's layout hides undeclared ones.","Reinstall after pulling changes that touch dependencies.","Treat \"package not found\" as a cause: read error.cause to find which specifier failed."],"tags":["build","dependencies","pnpm","resolution"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}