abhigyanpatwari/GitNexus · error · Error
Analyzer build symbolic links are not supported; materialize
Error message
Analyzer build symbolic links are not supported; materialize the build tree: ${entry.absolutePath} What it means
The build-tree receipt hashes real file content, but Node resolves imports through symlinks, so a symlink's target bytes outside buildRoot could change analyzer behaviour without changing anything the receipt covered (target containment, cycles, TOCTOU are all unsolved at that boundary). Rather than invent an incomplete trust model, the scan rejects any symbolic link inside the build tree and asks for a materialized (fully copied) tree.
Source
Thrown at gitnexus/src/core/analyzer-identity.ts:847
SHA256_PATTERN.test(cached.digest) &&
isDeepStrictEqual(cached.state, entry.state)
) {
digest = cached.digest;
} else if (entry.kind === 'file') {
const stable = hashStableFile(entry.absolutePath);
entry.state = stable.state.link;
digest = stable.digest;
options.onHashedInput?.({
kind: 'build',
path: entry.absolutePath,
bytes: stable.bytes,
});
} else if (entry.kind === 'symlink') {
// Imported files and directories are resolved through symlinks by Node.
// Hashing only link text would let bytes outside buildRoot change without
// changing the receipt. Reject them instead of inventing an incomplete
// recursive trust boundary (target containment, cycles, and TOCTOU).
throw new Error(
`Analyzer build symbolic links are not supported; materialize the build tree: ${entry.absolutePath}`,
);
}
updateCanonicalFrame(hash, [
'build-entry',
entry.relativePath,
entry.kind,
digest ? digestBytes(digest) : Buffer.alloc(0),
]);
nextEntries.push({
relativePath: entry.relativePath,
kind: entry.kind,
state: entry.state,
...(digest ? { digest } : {}),
});
}
View on GitHub (pinned to aac7515d2a)
Solutions
- Replace the link with a real copy: 'cp -Lr <link> <real-dir> && rm <link>' (materialize the tree).
- Configure the package manager to hoist/materialize instead of linking the gitnexus install (e.g. pnpm node-linker=hoisted for this dependency).
- Run gitnexus from a plain npm-style install where dist/ is real files.
- Change build tooling so post-build symlinking of dist subdirectories never runs in environments that execute analyze.
Example fix
# before: dist/vendor-grammars -> ../../shared-grammars (symlink) $ ls -l dist/vendor-grammars lrwxrwxrwx dist/vendor-grammars -> ../../shared-grammars # after: materialize the tree $ rm dist/vendor-grammars && cp -r ../../shared-grammars dist/vendor-grammars
Defensive patterns
Strategy: validation
Validate before calling
import { lstatSync, readdirSync } from 'node:fs';
function buildTreeHasNoSymlinks(buildRoot: string): boolean {
const stack = [buildRoot];
while (stack.length > 0) {
const dir = stack.pop()!;
for (const entry of readdirSync(dir, { withFileTypes: true })) {
if (entry.isSymbolicLink()) return false;
if (entry.isDirectory()) stack.push(`${dir}/${entry.name}`);
}
}
return true;
} Type guard
function isBuildSymlinkError(error: unknown): boolean {
return error instanceof Error && /^Analyzer build symbolic links are not supported/.test(error.message);
} Try / catch
try {
identity = resolveAnalyzerRunnerIdentity(import.meta.url);
} catch (error) {
if (isBuildSymlinkError(error)) {
reportUserError('Materialize the build tree: replace links inside dist with real copies (cp -Lr).');
}
throw error;
} Prevention
- Use a hoisted/materialized install for the environment running gitnexus (e.g. pnpm node-linker=hoisted).
- Never symlink subdirectories into dist in deploy scripts.
- Verify with find dist -type l before running analyze on custom builds.
When it happens
Trigger: Any entry classified as a symlink during collectBuildEntries/hashing — typically a pnpm-style or workspace install where parts of dist/ are links into a shared store, a developer manually symlinking a subdirectory (dist/vendor -> ../../shared), or a monorepo linking gitnexus's dist to a central location while running analyze against the link path.
Common situations: pnpm workspaces or custom linkers exposing the analyzer build through symlinks; developers symlinking shared grammars or vendored modules into dist; Docker volume or deploy tooling replacing directories with links.
Related errors
- Analyzer build scan exceeded ${limits.buildEntries} entries:
- Analyzer build scan exceeded depth ${limits.buildDepth}: ${a
- Analyzer build scan exceeded ${limits.buildBytes} bytes: ${b
- Unsupported analyzer build entry: ${absolutePath}
- Analyzer package lock symbolic link does not resolve to a fi
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/77f10a0d9b00ac6c.
Report an issue: GitHub.