abhigyanpatwari/GitNexus · error

Analyzer build or dependency runtime changed while its…

Error message

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

What it means

Before persisting the new identity cache, validateIdentityCache() re-checks every recorded guard (file stat states, directory states, path guards) captured during computation. If any guard now fails — or validation itself reports a failure via onCacheValidationFailure — the environment changed between hashing and persistence, and the error is thrown with the failing guard mode and path appended. This closes the window where a valid-looking identity could be cached for a mutated tree.

Solutions

  1. Re-run analyze after the concurrent modification finishes — the message's guard path tells you exactly which file/directory raced.
  2. Disable or reschedule backup/antivirus scans over node_modules and the gitnexus install during analysis.
  3. Ensure only one gitnexus process runs against an installation at a time.
  4. For self-built installs, finish builds before analysis; do not run identity resolution while tsc watch is active.

Example fix

# before
$ npx gitnexus analyze
# Analyzer build or dependency runtime changed ... (failed file guard: /.../dist/cli.js)

# after: wait for the racing writer, then retry
$ wait   # or stop the concurrent npm install / tsc watch
$ npx gitnexus analyze
Defensive patterns

Strategy: retry

Validate before calling

// The guard path in the message identifies the raced file; pre-check quiescence:
import { statSync } from 'node:fs';
function fileQuiescent(path: string, ms = 1000): boolean {
  const a = statSync(path); 
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
  const b = statSync(path);
  return a.mtimeMs === b.mtimeMs && a.size === b.size;
}

Try / catch

try {
  await analyze({ repo: '.' });
} catch (err) {
  const m = /failed (\w+) guard: (.+)\)/.exec(String((err as Error).message));
  if (err instanceof Error && err.message.includes('changed while its identity was being computed') && m) {
    logger.warn(`Raced ${m[1]} guard at ${m[2]}; retrying after quiescence`);
    await waitForQuiescent(m[2]);
    return analyze({ repo: '.' });
  }
  throw err;
}

Prevention

When it happens

Trigger: resolveAnalyzerRunnerIdentity() completing its hashing but failing validateIdentityCache(nextCache): a guarded file's size/mtime/inode changed, a guarded directory was replaced, or a guarded path vanished — all between guard capture and validation. Any concurrent writer (install, rebuild, sync tool) to packageRoot/buildRoot can cause it.

Common situations: Same family as errors 70/71 but detected via guards at persistence time: postinstall scripts finishing late, antivirus touching files, timestamp updates from backup tools, or a second gitnexus process writing to the same install.

Related errors


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

Appendix: source

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

      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 52924ef12c)