{"record":{"id":"5403cf19b5bc1bf5","repo":"JuliusBrussee/caveman","slug":"caveman-build-aliased-source-loader-is-not-lockab","errorCode":null,"errorMessage":"caveman build: aliased source loader is not lockable in ${JSON.stringify(path)}","messagePattern":"caveman build: aliased source loader is not lockable in (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/source-graph.ts","lineNumber":410,"sourceCode":"  }\n  cursor = skipSourceTrivia(source, cursor);\n  const fromEnd = consumeIdentifierToken(source, cursor, \"from\");\n  if (fromEnd === undefined) return undefined; // Local named type export.\n  cursor = skipSourceTrivia(source, fromEnd);\n  const literal = readQuotedSpecifier(source, cursor, path);\n  if (literal === undefined) throw sourceSyntaxError(path);\n  return literal.specifier;\n}\n\nfunction legacySourceSpecifiers(source: string, path: string, code: Uint8Array): string[] {\n  const trivia = String.raw`(?:\\s|\\/\\*[\\s\\S]*?\\*\\/|\\/\\/[^\\r\\n]*(?:\\r?\\n|$))*`;\n  const loaderAliases = [\n    new RegExp(String.raw`\\bcreateRequire${trivia}\\(`),\n    new RegExp(String.raw`\\b(?:const|let|var)${trivia}[A-Za-z_$][\\w$]*${trivia}=${trivia}require\\b`),\n    new RegExp(String.raw`\\b(?:const|let|var)${trivia}[A-Za-z_$][\\w$]*${trivia}=${trivia}URL\\b`),\n  ];\n  if (loaderAliases.some((pattern) => hasCodeMatch(source, pattern, code))) {\n    throw new Error(`caveman build: aliased source loader is not lockable in ${JSON.stringify(path)}`);\n  }\n  const specifiers: string[] = [];\n  for (const match of source.matchAll(LEGACY_LOAD_START_PATTERN)) {\n    const start = match.index;\n    const keyword = match[0]!;\n    if (!code[start] || !isIdentifierTokenAt(source, start, keyword)) continue;\n    if (keyword === \"module\") {\n      assertNoModuleRequireAlias(source, start, path);\n      continue;\n    }\n    if (keyword === \"Reflect\") {\n      assertNoReflectRequireAlias(source, start, path, code);\n      continue;\n    }\n    if (keyword === \"globalThis\") {\n      assertNoGlobalLoaderAlias(source, start, path);\n      continue;\n    }","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/source-graph.ts#L392-L428","documentation":"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.","triggerScenarios":"Source contains `const req = createRequire(import.meta.url);`, `const r = require;`, or `const myUrl = URL;`-style aliasing followed by indirect loads.","commonSituations":"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.","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)."],"exampleFix":"// before\nconst req = createRequire(import.meta.url);\nconst data = req(\"./data.json\");\n\n// after\nimport data from \"./data.json\" with { type: \"json\" };","handlingStrategy":"validation","validationCode":"const ALIAS_PATTERNS = [\n  /\\bcreateRequire\\s*\\(/,\n  /\\b(?:const|let|var)\\s+[A-Za-z_$][\\w$]*\\s*=\\s*require\\b/,\n  /\\b(?:const|let|var)\\s+[A-Za-z_$][\\w$]*\\s*=\\s*URL\\b/,\n];\nfunction usesAliasedLoader(source: string): boolean {\n  return ALIAS_PATTERNS.some((p) => p.test(source));\n}","typeGuard":null,"tryCatchPattern":"try {\n  await buildSourceGraph(root);\n} catch (error) {\n  if (error instanceof Error && error.message.includes(\"aliased source loader is not lockable\")) {\n    // file path is in the message; inline require/createRequire at each load site\n  } else throw error;\n}","preventionTips":["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."],"tags":["build","commonjs","require","static-analysis","lockability"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}