abhigyanpatwari/GitNexus · error

must be outside the analyzer package and build roots

Error message

${TRUSTED_CACHE_DIRECTORY_ENV} must be outside the analyzer package and build roots

What it means

Even a valid, real, absolute GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR is rejected if it lies inside the analyzer package root or build root. A cache nested inside the trees being hashed would create a feedback loop: persisting a cache entry changes the hashed inputs, invalidating the identity it just computed and defeating the tamper guards.

Solutions

  1. Move the cache outside the installation: export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/var/cache/gitnexus-identity (create it first).
  2. In CI, cache an external directory and mount/restore it at a path outside the package and build roots.
  3. If you do not need a custom location, unset the variable and use the default cache directory.
  4. Note options.cacheDirectory (programmatic) is exempt — only the env-var path enforces this rule.

Example fix

# before
export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/usr/lib/node_modules/gitnexus/.id-cache
# ...must be outside the analyzer package and build roots

# after
sudo mkdir -p /var/cache/gitnexus-identity && sudo chown "$USER" /var/cache/gitnexus-identity
export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/var/cache/gitnexus-identity
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the configured cache dir is outside the install tree:
import { relative, isAbsolute } from 'node:path';
function cacheDirOutsideRoots(cacheDir: string, packageRoot: string, buildRoot: string): boolean {
  const outside = (root: string) => {
    const rel = relative(resolve(root), resolve(cacheDir));
    return rel === '' || rel.startsWith('..') || isAbsolute(rel) ? !(rel === '') : false;
  };
  return outside(packageRoot) && outside(buildRoot);
}

Try / catch

try {
  spawnSync('gitnexus', ['analyze']);
} catch (err) {
  if (String((err as Error).message).includes('must be outside the analyzer package and build roots')) {
    delete process.env.GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR; // fall back to the default cache
    return spawnSync('gitnexus', ['analyze']);
  }
  throw err;
}

Prevention

When it happens

Trigger: cacheDirectory() computing isInside(packageRoot, configured) || isInside(buildRoot, configured) as true — e.g. the env var set to <packageRoot>/.identity-cache or <packageRoot>/node_modules/... while resolveAnalyzerRunnerIdentity() runs against that same package.

Common situations: Users tucking the cache 'neatly' inside the install dir, Docker images copying a cached directory into the package, or CI caching configurations that write into node_modules/gitnexus.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@52924ef12c (2026-08-20). Data as JSON: /api/errors/35d8499891aaeabc. Report an issue: GitHub.

Appendix: source

Thrown at gitnexus/src/core/analyzer-identity.ts:2114

): string | null {
  // An explicit location is a trusted operator/test override and therefore
  // remains authoritative, including when the secure default is unavailable.
  if (options.cacheDirectory) {
    const explicit = path.resolve(options.cacheDirectory);
    try {
      // Create it before any build/dependency directory guards are captured.
      // A cache nested immediately under a package root then changes that
      // parent's directory state once, not after we persist the first entry.
      mkdirSync(explicit, { recursive: true, mode: 0o700 });
    } catch {
      /* persistence remains optional and will fail closed */
    }
    return explicit;
  }
  const configured = trustedEnvironmentCacheDirectory();
  if (configured) {
    if (isInside(packageRoot, configured) || isInside(buildRoot, configured)) {
      throw new Error(
        `${TRUSTED_CACHE_DIRECTORY_ENV} must be outside the analyzer package and build roots`,
      );
    }
    return configured;
  }
  return defaultCacheDirectory();
}

function hasTrustedCacheOverride(options: AnalyzerIdentityResolveOptions): boolean {
  return (
    options.cacheDirectory !== undefined || process.env[TRUSTED_CACHE_DIRECTORY_ENV] !== undefined
  );
}

function identityCacheKey(
  packageRoot: string,
  buildRoot: string,
  runtimeVariant: RuntimeVariant,

View on GitHub (pinned to 52924ef12c)