{"record":{"id":"0c0c440b7ae3ac5e","repo":"abhigyanpatwari/GitNexus","slug":"analyzer-build-or-dependency-runtime-changed-while","errorCode":null,"errorMessage":"Analyzer build or dependency runtime changed while its identity was being computed: ${packageRoot}${mismatch}","messagePattern":"Analyzer build or dependency runtime changed while its identity was being computed: (.+?)(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/analyzer-identity.ts","lineNumber":2801,"sourceCode":"      rootPath: buildRoot,\n      canonicalization: BUILD_CANONICALIZATION,\n      digest: build.digest,\n    },\n    dependencyRuntime: dependency.identity,\n  };\n  let validationFailure: { mode: CacheGuardRequest['mode']; path: string } | undefined;\n  const validationOptions: AnalyzerIdentityResolveOptions = {\n    ...options,\n    onCacheValidationFailure: (failure) => {\n      validationFailure = failure;\n      options.onCacheValidationFailure?.(failure);\n    },\n  };\n  if (!validateIdentityCache(nextCache, validationOptions)) {\n    const mismatch = validationFailure\n      ? ` (failed ${validationFailure.mode} guard: ${validationFailure.path})`\n      : '';\n    throw new Error(\n      `Analyzer build or dependency runtime changed while its identity was being computed: ${packageRoot}${mismatch}`,\n    );\n  }\n  rememberIdentityCache(nextCache);\n  persistIdentityCache(packageRoot, buildRoot, nextCache, previousCache, options);\n  return identity;\n}\n\n/**\n * Semantic freshness comparison. Both receipts must be well-formed schema-v4\n * values; only the diagnostic entrypoint field is normalized away.\n */\nexport function analyzerRunnerIdentitiesEqual(\n  indexedIdentity: unknown,\n  currentIdentity: unknown,\n): boolean {\n  const indexed = normalizeAnalyzerRunnerIdentityForComparison(indexedIdentity);\n  const current = normalizeAnalyzerRunnerIdentityForComparison(currentIdentity);","sourceCodeStart":2783,"sourceCodeEnd":2819,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/analyzer-identity.ts#L2783-L2819","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make the filesystem quiescent during identity resolution (stop editors, watchers, installers, AV scans on the project tree).","Retry once on a quiet system — the validation is designed to surface genuine races, and a clean retry typically succeeds.","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.","For network filesystems, run the analyzer against a local checkout to eliminate stat divergence."],"exampleFix":"// before: editor's format-on-save rewrites package.json mid-resolution\n//   -> \"Analyzer build or dependency runtime changed while its identity was\n//       being computed: /repo (failed readable-file guard: /repo/package.json)\"\n//\n// after: disable format-on-save / close the editor, then retry\n//   $ git stash  # remove pending edits\n//   $ node .gitnexus/run.cjs analyze --index-only","handlingStrategy":"retry","validationCode":"// No deterministic pre-check exists (the guard compares two stat passes), but you can reduce divergence:\nfunction warnIfCoarseMtime(packageRoot) {\n  // Many filesystems (some network/overlay) have >1ms mtime granularity -> spurious guard failures.\n  // Detect by writing twice in quick succession and comparing mtimes.\n  const fs = require('node:fs');\n  const path = require('node:path');\n  const tmp = path.join(packageRoot, `.gn-mtime-probe-${process.pid}`);\n  fs.writeFileSync(tmp, 'a'); const t1 = fs.statSync(tmp).mtimeMs;\n  fs.writeFileSync(tmp, 'b'); const t2 = fs.statSync(tmp).mtimeMs;\n  fs.rmSync(tmp);\n  if (t1 === t2) console.warn(`Filesystem mtime granularity is coarse on ${packageRoot}; identity validation may race.`);\n}\n// warnIfCoarseMtime(process.cwd());","typeGuard":null,"tryCatchPattern":"try {\n  identity = resolveAnalyzerRunnerIdentity(analyzerModuleUrl, options);\n} catch (err) {\n  if (err.message.startsWith('Analyzer build or dependency runtime changed while its identity was being computed:')) {\n    // Final-boundary TOCTOU; the message names the failing guard mode+path.\n    // One retry on a quiescent tree is reasonable; repeated failures indicate a real concurrent writer.\n    identity = resolveAnalyzerRunnerIdentity(analyzerModuleUrl, options);\n  } else throw err;\n}","preventionTips":["Make the project filesystem quiescent during identity resolution: stop editors (format-on-save), watchers, installers, and AV scans.","Inspect the failed guard mode in the message: 'directory-inventory' = dir entries changed; 'readable-file' = file stat changed; 'link' = symlink target changed.","Run the analyzer against a local checkout rather than a network/overlay filesystem to avoid stat divergence.","A single retry is acceptable; a repeat means a genuine concurrent writer that must be fixed in your pipeline."],"tags":["analyzer-identity","toctou","concurrency","cache-validation"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}