JuliusBrussee/caveman · error
caveman build: source module syntax is not lexable in ${JSON
Error message
caveman build: source module syntax is not lexable in ${JSON.stringify(path)} What it means
esmSourceSpecifiers() runs es-module-lexer's parse() over a source file and throws this error when parsing itself fails, wrapping the lexer error as cause. If the file cannot be lexed as an ES module, its import graph cannot be extracted, so the source closure is not computable and the build aborts with the file path in the message.
Source
Thrown at packages/agent/src/source-graph.ts:276
return undefined;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
function isPathWithin(root: string, candidate: string): boolean {
const child = relative(root, candidate);
return child === "" || (!isAbsolute(child) && child !== ".." &&
!child.startsWith("../") && !child.startsWith("..\\"));
}
function esmSourceSpecifiers(source: string, path: string): string[] {
let imports: ReturnType<typeof parse>[0];
try {
[imports] = parse(source, path);
} catch (error) {
throw new Error(
`caveman build: source module syntax is not lexable in ${JSON.stringify(path)}`,
{ cause: error },
);
}
const specifiers: string[] = [];
for (const item of imports) {
if (item.d === -2) continue; // import.meta is metadata, not a dependency.
if (item.n === undefined) {
throw new Error(`caveman build: computed source dependency is not lockable in ${JSON.stringify(path)}`);
}
specifiers.push(item.n);
}
return specifiers;
}
function typescriptSourceSyntax(
source: string,
path: string,View on GitHub (pinned to 27d5a3981a)
Solutions
- Open the path from the error message and fix the syntax error; the cause error carries the lexer's line/column.
- Run your normal lint/tsc pass before building so broken files fail there first.
- If the syntax is valid-but-new, pin a newer framework/lexer version that supports it.
Example fix
// before: src/broken.js export const = bad syntax; // after export const value = "fixed";
Defensive patterns
Strategy: try-catch
Validate before calling
import { parse } from "es-module-lexer";
function isLexable(source: string, path: string): boolean {
try { parse(source, path); return true; } catch { return false; }
} Try / catch
try {
await buildSourceGraph(root);
} catch (error) {
if (error instanceof Error && error.message.includes("source module syntax is not lexable")) {
// file path is in the message; error.cause carries the lexer error with line/column
} else throw error;
} Prevention
- Run lint/tsc before build so syntax errors fail early.
- Avoid committing half-edited files; use --fix or revert before building.
- The cause error has the lexer's position — read error.cause, not just the wrapper.
When it happens
Trigger: A .js/.mjs file with a genuine syntax error, or syntax the lexer version cannot handle (e.g. very new ECMAScript proposals or malformed code) anywhere in the reachable project graph.
Common situations: Building while the working tree has a half-edited file; a tool or codegen step emitting invalid JS; an es-module-lexer version lagging behind bleeding-edge syntax used in sources.
Related errors
- cave_eve_terminal_${result.status}
- cave_harness_upstream_version_mismatch
- caveman build: dataResidency is not enforced yet; refusing t
- caveman build: requiredFixturePassRate must be in (0,1]
- caveman build: qualityRetention must be in (0,1]
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/d6d431a63b2aa9fc.
Report an issue: GitHub.