abhigyanpatwari/GitNexus · error · Error
Analyzer package-lock lookup exceeded ${limits.resolutionAnc
Error message
Analyzer package-lock lookup exceeded ${limits.resolutionAncestors} ancestors: ${packageRoot} What it means
findNearestPackageLock() walks from the package root up through ancestors looking for package-lock.json, counting one ancestor per iteration and throwing past limits.resolutionAncestors (default 256). The walk must actually visit each level (it stats and records a guard per candidate), so the count also bounds the loop against pathological or cyclic-looking path structures. 256 levels is far deeper than any real install, so hitting it almost always means a constructed layout.
Source
Thrown at gitnexus/src/core/analyzer-identity.ts:951
candidate: string,
): DependencyPathGuardResult {
if (guards.has(candidate)) return guards.get(candidate) ?? null;
const result = snapshotDependencyPathGuard(candidate);
guards.set(candidate, result);
return result;
}
function findNearestPackageLock(
packageRoot: string,
pathGuards: Map<string, DependencyPathGuardResult>,
limits: AnalyzerIdentityTraversalLimits,
): string | null {
let cursor = packageRoot;
let ancestors = 0;
while (true) {
ancestors += 1;
if (ancestors > limits.resolutionAncestors) {
throw new Error(
`Analyzer package-lock lookup exceeded ${limits.resolutionAncestors} ancestors: ${packageRoot}`,
);
}
const candidate = path.join(cursor, 'package-lock.json');
recordDependencyPathGuard(pathGuards, candidate);
// Preserve the link path so ReadableFileState guards both the link and its
// resolved target. Realpathing here would miss a later retarget while the
// old target remained unchanged.
try {
const link = lstatSync(candidate);
if (link.isFile()) return path.resolve(candidate);
if (link.isSymbolicLink()) {
try {
const target = statSync(candidate);
if (!target.isFile()) {
throw new Error(
`Analyzer package lock symbolic link does not resolve to a file: ${candidate}`,
);View on GitHub (pinned to 52924ef12c)
Solutions
- Move the gitnexus install to a normal-depth location; real installs are dozens of levels deep at most.
- In tests, only tighten resolutionAncestors when the fixture genuinely has few ancestor levels, and keep it above the actual depth.
- Verify no mount/bind arrangement creates an effectively unbounded parent chain.
Defensive patterns
Strategy: try-catch
Type guard
function isLockfileAncestorLimitError(error: unknown): boolean {
return error instanceof Error && /^Analyzer package-lock lookup exceeded \d+ ancestors:/.test(error.message);
} Try / catch
try {
identity = resolveAnalyzerRunnerIdentity(import.meta.url);
} catch (error) {
if (isLockfileAncestorLimitError(error)) {
reportUserError('Install path is pathologically deep; move gitnexus to a normal-depth directory.');
}
throw error;
} Prevention
- Install global tools at conventional paths, not inside deeply nested temp trees.
- In tests, keep resolutionAncestors above the fixture's real ancestor depth.
When it happens
Trigger: The GitNexus package root sits more than 256 directory levels below the filesystem root, or a test set resolutionAncestors to a tiny value via traversalLimits. Because the loop increments before checking, even the first level counts, so a limit of 1 throws on any non-root start.
Common situations: Tests tightening resolutionAncestors for speed; pathologically nested temp/fixture directories (build tools that mirror deep scoped package names); a filesystem loop presented through mounts.
Related errors
- Analyzer runtime scan exceeded ${maxBytes} bytes: ${candidat
- Analyzer build scan exceeded ${limits.buildEntries} entries:
- Analyzer build scan exceeded depth ${limits.buildDepth}: ${a
- Analyzer build scan exceeded ${limits.buildBytes} bytes: ${b
- Analyzer package lock symbolic link does not resolve to a fi
AI-assisted analysis of abhigyanpatwari/GitNexus@52924ef12c (2026-08-20).
Data as JSON: /api/errors/f288ac6e950eeea6.
Report an issue: GitHub.