abhigyanpatwari/GitNexus · error · Error
Analyzer identity input changed while it was being hashed: $
Error message
Analyzer identity input changed while it was being hashed: ${candidate} What it means
hashStableFile() streams a file through a 256 KiB buffer, hashing as it goes, and validates that the stat snapshot taken before the open, the fstat of the opened descriptor, the byte count actually read, and a fresh stat after reading all agree; after two failed attempts it declares the input unstable. The receipt hash must reflect exact bytes, so a file mutated while being hashed (changed size, mtime, or inode) is rejected rather than hashed incorrectly.
Source
Thrown at gitnexus/src/core/analyzer-identity.ts:585
bytes += read;
if (bytes > expectedBytes) break;
}
const openedAfter = statState(fstatSync(descriptor, { bigint: true }));
closeSync(descriptor);
descriptor = null;
const after = snapshotReadableFile(candidate);
if (
bytes === expectedBytes &&
isDeepStrictEqual(openedBefore, openedAfter) &&
isDeepStrictEqual(before, after)
) {
return { digest: `sha256:${hash.digest('hex')}`, state: after, bytes };
}
} finally {
if (descriptor !== null) closeSync(descriptor);
}
}
throw new Error(`Analyzer identity input changed while it was being hashed: ${candidate}`);
}
function resolveExistingPath(candidate: string): string {
return realpathSync.native(path.resolve(candidate));
}
/**
* Case-stabilize a path's Windows drive letter so two processes that observed
* the same directory under different drive-letter casing (`c:\…` vs `C:\…`)
* produce byte-identical analyzer-identity path fields (#2668).
*
* `realpathSync.native` canonicalizes 8.3 short names and symlinks but does not
* guarantee the drive-letter case it returns — it can preserve whatever casing
* the caller's path carried, and `import.meta.url` casing depends on how each
* entry process (CLI shim vs `npx`/npm wrapper vs server worker) was launched.
* When `analyze` stamps `build.rootPath` under one casing and `status`
* recomputes it under another, `analyzerRunnerIdentitiesEqual` deep-compares
* unequal and `status` reports a freshly-analyzed, untouched repo as stale.View on GitHub (pinned to aac7515d2a)
Solutions
- Re-run analyze after builds, installs, and sync tools are quiescent.
- Sequence CI steps so 'gitnexus analyze' runs strictly after the install/build step, not in parallel.
- Exclude the gitnexus install and dist directories from cloud-sync folders and real-time antivirus scanning.
- For programmatic use, retry the resolve a bounded number of times (same pattern as error 40).
Example fix
// before
const identity = resolveAnalyzerRunnerIdentity(import.meta.url);
// after
async function resolveWithRetry(url: string, tries = 3) {
for (let i = 0; ; i += 1) {
try {
return resolveAnalyzerRunnerIdentity(url);
} catch (error) {
const message = String((error as Error).message);
if (i === tries - 1 || !/changed while (it was being|its identity was being)/.test(message)) throw error;
await new Promise((resolve) => setTimeout(resolve, 250 * (i + 1)));
}
}
} Defensive patterns
Strategy: retry
Type guard
function isIdentityHashChangedError(error: unknown): boolean {
return error instanceof Error && /^Analyzer identity input changed while it was being hashed:/.test(error.message);
} Try / catch
for (let attempt = 0; attempt < 3; attempt += 1) {
try {
identity = resolveAnalyzerRunnerIdentity(import.meta.url);
break;
} catch (error) {
if (!isIdentityHashChangedError(error) || attempt === 2) throw error;
await sleep(250 * (attempt + 1));
}
} Prevention
- Finish builds (tsc/esbuild/vite) before running analyze; stop watch mode first.
- Keep the gitnexus dist/ out of cloud-sync folders.
- Serialize CI stages so analyze never overlaps the stage that writes dist or node_modules.
When it happens
Trigger: Reached for every build-tree file and hashed runtime artifact during resolveAnalyzerRunnerIdentity — e.g. 'gitnexus analyze' hashing dist/ while a bundler/watcher (tsc --watch, esbuild, vite) rewrites a .js/.wasm/.node file, or an install/upgrade process replaces files under node_modules or dist mid-scan.
Common situations: Running gitnexus in one terminal while 'npm run build'/'npm install' runs in another; Docker volume mounts with lazy materialization mutating mtimes; synced folders (Dropbox/OneDrive) downloading files during the scan; antivirus rewriting files after inspection on Windows.
Related errors
- Analyzer identity input changed while it was being read: ${c
- Analyzer runtime payload directory is unavailable: ${absolut
- Analyzer runtime scan exceeded ${maxBytes} bytes: ${candidat
- Unsupported analyzer build entry: ${absolutePath}
- Analyzer package lock symbolic link does not resolve to a fi
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/0e6da692145431ff.
Report an issue: GitHub.