abhigyanpatwari/GitNexus · error

must name an absolute protected directory

Error message

${TRUSTED_CACHE_DIRECTORY_ENV} must name an absolute protected directory

What it means

GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR is an explicit trust assertion pointing the analyzer-identity cache at a specific directory, so its spelling is validated strictly: it must be non-empty, contain no NUL bytes, and be an absolute path. Any relative path (or empty/NUL-containing value) is rejected immediately with this error before any filesystem access.

Solutions

  1. Use an absolute path: export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/var/cache/gitnexus-identity.
  2. If composing from a variable, expand explicitly: export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR="$PWD/.gitnexus/identity-cache".
  3. Expand ~ manually ($HOME/...) — the validator does not perform shell expansion.
  4. Unset the variable entirely if you want the default secure cache location.

Example fix

# before
export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=.cache/identity
npx gitnexus analyze
# GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR must name an absolute protected directory

# after
export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR="$PWD/.cache/identity"
npx gitnexus analyze
Defensive patterns

Strategy: validation

Validate before calling

// Validate before launching the CLI:
import { isAbsolute } from 'node:path';
function validIdentityCacheEnv(value: string | undefined): boolean {
  return value === undefined ||
    (value.length > 0 && !value.includes('\0') && isAbsolute(value));
}
if (!validIdentityCacheEnv(process.env.GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR)) {
  throw new Error('Set GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR to an absolute path or unset it');
}

Try / catch

try {
  execSync('npx gitnexus analyze');
} catch (err) {
  if (String((err as Error).message).includes('must name an absolute protected directory')) {
    process.env.GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR = resolve(process.env.GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR!);
    return execSync('npx gitnexus analyze');
  }
  throw err;
}

Prevention

When it happens

Trigger: Setting GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR to a relative path like '.cache/identity' or '~/.gitnexus-cache' (tilde is not expanded), an empty string, or a value with embedded NUL, then running any command that resolves the analyzer identity (analyze, query, MCP server start).

Common situations: CI scripts and .env files using relative paths; Windows-style paths on POSIX or vice versa; shell quoting mistakes that leave the variable empty (GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR= with trailing space).

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


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

Appendix: source

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

  try {
    tempRoot = realpathSync.native(os.tmpdir());
  } catch {
    return null;
  }
  return ensurePrivateChild(tempRoot, `gitnexus-analyzer-identity-${uid}`);
}

const TRUSTED_CACHE_DIRECTORY_ENV = 'GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR';

function pathsEqual(left: string, right: string): boolean {
  return process.platform === 'win32' ? left.toLowerCase() === right.toLowerCase() : left === right;
}

function trustedEnvironmentCacheDirectory(): string | null {
  const configured = process.env[TRUSTED_CACHE_DIRECTORY_ENV];
  if (configured === undefined) return null;
  if (configured.length === 0 || configured.includes('\0') || !path.isAbsolute(configured)) {
    throw new Error(`${TRUSTED_CACHE_DIRECTORY_ENV} must name an absolute protected directory`);
  }
  const normalized = path.normalize(configured);
  let resolved: string;
  try {
    const link = lstatSync(normalized);
    if (!link.isDirectory() || link.isSymbolicLink()) {
      throw new Error('not a real directory');
    }
    resolved = realpathSync.native(normalized);
  } catch {
    throw new Error(
      `${TRUSTED_CACHE_DIRECTORY_ENV} must name a pre-existing protected non-symlink directory`,
    );
  }
  // Reject junctions/symlinked ancestors as well as a symlink final component.
  // The environment variable is an explicit trust assertion, but its spelling
  // must still bind exactly to the directory the cache will use.
  if (!pathsEqual(path.resolve(normalized), resolved)) {

View on GitHub (pinned to 52924ef12c)