JuliusBrussee/caveman · error
caveman build: aliased source loader is not lockable in ${JS
Error message
caveman build: aliased source loader is not lockable in ${JSON.stringify(path)} What it means
legacySourceSpecifiers() scans CommonJS-style sources with comment-aware regexes and throws when it detects a loader alias: a call to createRequire(...), or a const/let/var initialized to `require` or `URL`. Once require or import.meta.url is captured into a variable, the scanner can no longer track which files are loaded through it, so the closure is not lockable and the file path is reported.
Source
Thrown at packages/agent/src/source-graph.ts:410
}
cursor = skipSourceTrivia(source, cursor);
const fromEnd = consumeIdentifierToken(source, cursor, "from");
if (fromEnd === undefined) return undefined; // Local named type export.
cursor = skipSourceTrivia(source, fromEnd);
const literal = readQuotedSpecifier(source, cursor, path);
if (literal === undefined) throw sourceSyntaxError(path);
return literal.specifier;
}
function legacySourceSpecifiers(source: string, path: string, code: Uint8Array): string[] {
const trivia = String.raw`(?:\s|\/\*[\s\S]*?\*\/|\/\/[^\r\n]*(?:\r?\n|$))*`;
const loaderAliases = [
new RegExp(String.raw`\bcreateRequire${trivia}\(`),
new RegExp(String.raw`\b(?:const|let|var)${trivia}[A-Za-z_$][\w$]*${trivia}=${trivia}require\b`),
new RegExp(String.raw`\b(?:const|let|var)${trivia}[A-Za-z_$][\w$]*${trivia}=${trivia}URL\b`),
];
if (loaderAliases.some((pattern) => hasCodeMatch(source, pattern, code))) {
throw new Error(`caveman build: aliased source loader is not lockable in ${JSON.stringify(path)}`);
}
const specifiers: string[] = [];
for (const match of source.matchAll(LEGACY_LOAD_START_PATTERN)) {
const start = match.index;
const keyword = match[0]!;
if (!code[start] || !isIdentifierTokenAt(source, start, keyword)) continue;
if (keyword === "module") {
assertNoModuleRequireAlias(source, start, path);
continue;
}
if (keyword === "Reflect") {
assertNoReflectRequireAlias(source, start, path, code);
continue;
}
if (keyword === "globalThis") {
assertNoGlobalLoaderAlias(source, start, path);
continue;
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Use require(...) / createRequire(...) directly at each load site instead of storing the loader in a variable.
- Prefer static ESM import declarations for project-internal files.
- Keep loader-wrapping utilities outside the locked project graph (as an installed dependency with a proper closure).
Example fix
// before
const req = createRequire(import.meta.url);
const data = req("./data.json");
// after
import data from "./data.json" with { type: "json" }; Defensive patterns
Strategy: validation
Validate before calling
const ALIAS_PATTERNS = [
/\bcreateRequire\s*\(/,
/\b(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*=\s*require\b/,
/\b(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*=\s*URL\b/,
];
function usesAliasedLoader(source: string): boolean {
return ALIAS_PATTERNS.some((p) => p.test(source));
} Try / catch
try {
await buildSourceGraph(root);
} catch (error) {
if (error instanceof Error && error.message.includes("aliased source loader is not lockable")) {
// file path is in the message; inline require/createRequire at each load site
} else throw error;
} Prevention
- Call require(...) or createRequire(...) inline at each load site — never store the loader in a binding.
- Prefer static import declarations for project files.
- Keep require-wrapping utilities in installed packages, not project sources.
When it happens
Trigger: Source contains `const req = createRequire(import.meta.url);`, `const r = require;`, or `const myUrl = URL;`-style aliasing followed by indirect loads.
Common situations: Standard-looking ESM/CJS interop shims in utility files; helper modules that wrap require to add caching or logging; code ported from bundler environments where aliasing require is idiomatic.
Related errors
- caveman build: computed source dependency is not lockable in
- 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]
- caveman build: config must export defineBuild()
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/5403cf19b5bc1bf5.
Report an issue: GitHub.