JuliusBrussee/caveman · error

caveman build: unresolved source dependency

Error message

caveman build: unresolved source dependency ${JSON.stringify(specifier)}

What it means

During 'caveman build' the source-graph walker resolves bare (package) import specifiers to files on disk. It first tries Node's createRequire().resolve, then a fallback resolver for import-only dependencies; if both fail, the dependency cannot be traced to source and this error is thrown with the specifier quoted and the original require error as cause.

Solutions

  1. Install the missing dependency (npm/pnpm install) so createRequire can resolve it
  2. If it's a workspace package, link it properly (workspaces config / pnpm link) or build its dist output
  3. Check package.json 'exports' of the dependency — a specifier pointing to a non-exported subpath will fail resolution
  4. Verify the specifier spelling against the actual package name

Example fix

// before
import { helper } from '@acme/utils';   // not installed
// after
$ npm install @acme/utils
import { helper } from '@acme/utils';
Defensive patterns

Strategy: validation

Validate before calling

import { createRequire } from 'module';
try {
  createRequire(importerPath).resolve(specifier);
} catch {
  throw new Error(`Install missing dependency: ${specifier}`);
}

Try / catch

try {
  await build({ files: sourceFiles(entry) });
} catch (e) {
  const m = /unresolved source dependency (.+)/.exec(e.message);
  if (m) console.error(`npm install ${JSON.parse(m[1])}`);
  else throw e;
}

Prevention

When it happens

Trigger: expandSourceGraph (via sourceFiles/graph/files) encounters a bare specifier whose package cannot be resolved from the importing file's path — package not installed, export map hides the entry, or monorepo workspace not linked.

Common situations: Forgetting 'npm/pnpm install' after adding a dependency; workspace package not linked in a monorepo; dependency only importable at runtime (bundled/aliased) so Node resolution fails; typos in the import specifier.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/409591381331725d. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/source-graph.ts:57

      ...esmSourceSpecifiers(typescript.lexableSource, path),
      ...typescript.specifiers,
      ...legacySourceSpecifiers(source, path, code),
    ]);
    for (const specifier of specifiers) {
      if (BUILTINS.has(specifier)) continue;
      const bare = !specifier.startsWith(".");
      if (bare && !includeBareDependencies) continue;
      let base: string;
      let packageRoot: string | undefined;
      if (bare) {
        packageRoot = dependencyPackageRoot(specifier, path);
        try {
          base = createRequire(path).resolve(specifier);
        } catch (requireError) {
          try {
            base = await resolveImportOnlyDependency(specifier, path);
          } catch {
            throw new Error(
              `caveman build: unresolved source dependency ${JSON.stringify(specifier)}`,
              { cause: requireError },
            );
          }
        }
      } else {
        base = resolve(dirname(path), specifier);
      }
      const candidates = extname(base)
        ? explicitImportCandidates(base, path)
        : [
          base,
          ...RESOLUTION_EXTENSIONS.map((extension) => base + extension),
          ...SOURCE_EXTENSIONS.map((extension) => resolve(base, `index${extension}`)),
        ];
      let found: string | undefined;
      for (const candidate of candidates) {
        try {

View on GitHub (pinned to 3ee70a1026)