{"record":{"id":"4a48d96736824051","repo":"JuliusBrussee/caveman","slug":"caveman-build-unresolved-relative-source-import","errorCode":null,"errorMessage":"caveman build: unresolved relative source import ${JSON.stringify(specifier)}","messagePattern":"caveman build: unresolved relative source import (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/source-graph.ts","lineNumber":84,"sourceCode":"      const candidates = extname(base)\n        ? explicitImportCandidates(base, path)\n        : [\n          base,\n          ...RESOLUTION_EXTENSIONS.map((extension) => base + extension),\n          ...SOURCE_EXTENSIONS.map((extension) => resolve(base, `index${extension}`)),\n        ];\n      let found: string | undefined;\n      for (const candidate of candidates) {\n        try {\n          await readFile(candidate);\n          found = candidate;\n          break;\n        } catch (error) {\n          if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n        }\n      }\n      if (!found) {\n        throw new Error(`caveman build: unresolved relative source import ${JSON.stringify(specifier)}`);\n      }\n      if (bare) {\n        await collectPackageClosure(packageRoot!, files, packageRoots);\n        continue;\n      }\n      const lexicalFound = found;\n      found = await realpath(found);\n      const insideRoot = isPathWithin(canonicalRoot, found);\n      if (!insideRoot && !bare && !external.has(path)) {\n        const lexicalInsideRoot = isPathWithin(canonicalRoot, lexicalFound);\n        if (lexicalInsideRoot) {\n          throw new Error(\"caveman build: source graph symlink escapes project root\");\n        }\n        throw new Error(\"caveman build: imported source escapes project root\");\n      }\n      if (!insideRoot) external.add(found);\n      if (!files.has(found)) {\n        files.add(found);","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/source-graph.ts#L66-L102","documentation":"The source-graph walker resolves relative imports by probing candidate files on disk, tolerating ENOENT while trying extensions, but if no candidate file is found it throws this error naming the unresolved relative specifier. It means a relative import in the traced source graph points at a file that does not exist.","triggerScenarios":"expandSourceGraph follows a relative import ('./x', '../y/z') and no matching file (with any supported extension) exists at that location from the importing file's directory.","commonSituations":"Typo in the relative path; file renamed/moved without updating imports; wrong letter-case on case-sensitive filesystems; import written with an extension variant the resolver does not probe.","solutions":["Fix the import specifier to match the actual file path/case","Create the missing file at the referenced location","If the module truly doesn't belong in the graph, make the import external/bare or exclude it from the source-graph traversal","Run a quick ls on the importing file's directory to confirm the exact filename and extension"],"exampleFix":"// before\nimport { render } from './Render.tsx';   // file is actually render.tsx\n// after\nimport { render } from './render.tsx';","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nimport { dirname, resolve } from 'path';\nif (!existsSync(resolve(dirname(importerPath), specifier))) {\n  throw new Error(`Relative import target missing: ${specifier}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await build({ files: sourceFiles(entry) });\n} catch (e) {\n  if (e.message.includes('unresolved relative source import')) {\n    console.error('Fix the import path/case:', e.message);\n  } else throw e;\n}","preventionTips":["Enable TS 'moduleResolution' + tsc/lint checks to catch missing files pre-build","Avoid renaming files without IDE-assisted import updates","Use consistent extension/casing conventions (lowercase filenames)"],"tags":["build","module-resolution","imports"],"backgroundTag":"file-not-found","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}