abhigyanpatwari/GitNexus · error · Error

Analyzer build or dependency runtime changed while its ident

Error message

Analyzer build or dependency runtime changed while its identity was being computed: ${packageRoot}${mismatch}

What it means

Thrown by resolveAnalyzerRunnerIdentity as the final consistency gate: after the identity is assembled and the next cache payload built, validateIdentityCache(nextCache, validationOptions) re-checks every directory-inventory / readable-file / link guard. If any guard fails (the filesystem state moved between the snapshot and this validation pass), the cache is rejected and the resolution aborts, optionally annotating which guard mode/path failed.

Source

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

      rootPath: buildRoot,
      canonicalization: BUILD_CANONICALIZATION,
      digest: build.digest,
    },
    dependencyRuntime: dependency.identity,
  };
  let validationFailure: { mode: CacheGuardRequest['mode']; path: string } | undefined;
  const validationOptions: AnalyzerIdentityResolveOptions = {
    ...options,
    onCacheValidationFailure: (failure) => {
      validationFailure = failure;
      options.onCacheValidationFailure?.(failure);
    },
  };
  if (!validateIdentityCache(nextCache, validationOptions)) {
    const mismatch = validationFailure
      ? ` (failed ${validationFailure.mode} guard: ${validationFailure.path})`
      : '';
    throw new Error(
      `Analyzer build or dependency runtime changed while its identity was being computed: ${packageRoot}${mismatch}`,
    );
  }
  rememberIdentityCache(nextCache);
  persistIdentityCache(packageRoot, buildRoot, nextCache, previousCache, options);
  return identity;
}

/**
 * Semantic freshness comparison. Both receipts must be well-formed schema-v4
 * values; only the diagnostic entrypoint field is normalized away.
 */
export function analyzerRunnerIdentitiesEqual(
  indexedIdentity: unknown,
  currentIdentity: unknown,
): boolean {
  const indexed = normalizeAnalyzerRunnerIdentityForComparison(indexedIdentity);
  const current = normalizeAnalyzerRunnerIdentityForComparison(currentIdentity);

View on GitHub (pinned to d540b00184)

Solutions

  1. Make the filesystem quiescent during identity resolution (stop editors, watchers, installers, AV scans on the project tree).
  2. Retry once on a quiet system — the validation is designed to surface genuine races, and a clean retry typically succeeds.
  3. Inspect the named failure path and mode in the message: a 'directory-inventory' guard failing means directory entries changed; 'readable-file' means file stat changed; 'link' means a symlink target changed.
  4. For network filesystems, run the analyzer against a local checkout to eliminate stat divergence.

Example fix

// before: editor's format-on-save rewrites package.json mid-resolution
//   -> "Analyzer build or dependency runtime changed while its identity was
//       being computed: /repo (failed readable-file guard: /repo/package.json)"
//
// after: disable format-on-save / close the editor, then retry
//   $ git stash  # remove pending edits
//   $ node .gitnexus/run.cjs analyze --index-only
Defensive patterns

Strategy: retry

Validate before calling

// No deterministic pre-check exists (the guard compares two stat passes), but you can reduce divergence:
function warnIfCoarseMtime(packageRoot) {
  // Many filesystems (some network/overlay) have >1ms mtime granularity -> spurious guard failures.
  // Detect by writing twice in quick succession and comparing mtimes.
  const fs = require('node:fs');
  const path = require('node:path');
  const tmp = path.join(packageRoot, `.gn-mtime-probe-${process.pid}`);
  fs.writeFileSync(tmp, 'a'); const t1 = fs.statSync(tmp).mtimeMs;
  fs.writeFileSync(tmp, 'b'); const t2 = fs.statSync(tmp).mtimeMs;
  fs.rmSync(tmp);
  if (t1 === t2) console.warn(`Filesystem mtime granularity is coarse on ${packageRoot}; identity validation may race.`);
}
// warnIfCoarseMtime(process.cwd());

Try / catch

try {
  identity = resolveAnalyzerRunnerIdentity(analyzerModuleUrl, options);
} catch (err) {
  if (err.message.startsWith('Analyzer build or dependency runtime changed while its identity was being computed:')) {
    // Final-boundary TOCTOU; the message names the failing guard mode+path.
    // One retry on a quiescent tree is reasonable; repeated failures indicate a real concurrent writer.
    identity = resolveAnalyzerRunnerIdentity(analyzerModuleUrl, options);
  } else throw err;
}

Prevention

When it happens

Trigger: validateIdentityCache walks all dependencyFileGuards, dependencyDirectoryGuards, dependencyPathGuards, and buildDirectoryGuards in nextCache, re-stating each; if any re-stat mismatches the recorded state, onCacheValidationFailure fires with {mode, path} and validateIdentityCache returns false. The throw message includes the failed mode and path when validationFailure was captured.

Common situations: Same class as errors 96/97 but caught at the FINAL return-boundary validation: a concurrent process touched a file/directory after the pre-hash snapshot but before this validation pass; an editor rewriting a manifest on save; an antivirus quarantining a file mid-resolution; a filesystem whose mtime/ctime resolution is coarse enough that two passes occasionally diverge; a network filesystem with eventual-consistency stat results.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/0c0c440b7ae3ac5e. Report an issue: GitHub.