{"record":{"id":"fbe68e0ae41e0ea1","repo":"Egonex-AI/Understand-Anything","slug":"previous-graph-commit-does-not-match-the-requested","errorCode":null,"errorMessage":"Previous graph commit does not match the requested base and no symbol baseline exists; cannot safely retry","messagePattern":"Previous graph commit does not match the requested base and no symbol baseline exists; cannot safely retry","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"understand-anything-plugin/skills/understand/prepare-incremental.mjs","lineNumber":523,"sourceCode":"  const graph = readJson(join(uaDir, 'knowledge-graph.json'), {});\n  const oldFingerprints = normalizeFingerprintStore(\n    readJson(join(uaDir, 'fingerprints.json'), null),\n    baseCommit,\n  );\n  const baselineSnapshotPath = join(intermediateDir, 'incremental-baseline.json');\n  const existingSnapshot = readJson(baselineSnapshotPath, null);\n  const baselineScan = existingSnapshot?.baseCommit === baseCommit\n    ? existingSnapshot.scan\n    : oldScan;\n  const baselineGraph = existingSnapshot?.baseCommit === baseCommit && existingSnapshot.graph\n    ? existingSnapshot.graph\n    : graph;\n  if (!Array.isArray(baselineGraph.nodes) || !Array.isArray(baselineGraph.edges)) {\n    throw new Error('A valid previous graph is required for incremental symbol protection');\n  }\n  if (existingSnapshot?.baseCommit !== baseCommit || !existingSnapshot.graph) {\n    if (graph?.project?.gitCommitHash && graph.project.gitCommitHash !== baseCommit) {\n      throw new Error('Previous graph commit does not match the requested base and no symbol baseline exists; cannot safely retry');\n    }\n    atomicWriteJson(baselineSnapshotPath, { baseCommit, scan: baselineScan, graph: baselineGraph });\n  }\n  // A failed prior attempt can leave complete or split analyzer batches behind.\n  // Remove only known internal scratch names before planning the retry so the\n  // merge cannot resurrect deleted nodes from stale output.\n  clearIncrementalScratch(intermediateDir);\n\n  const currentScanPath = join(intermediateDir, 'current-scan.json');\n  const currentScan = runScan(projectRoot, currentScanPath, args.excludePatterns);\n  const scanFailures = Array.isArray(currentScan?.failures) ? currentScan.failures : [];\n  if (scanFailures.length > 0) {\n    const preview = scanFailures\n      .slice(0, 5)\n      .map(failure => `${failure.path ?? '<global>'} (${failure.stage})`)\n      .join(', ');\n    const suffix = scanFailures.length > 5 ? ` (+${scanFailures.length - 5} more)` : '';\n    throw new Error(`Project scan reported failures: ${preview}${suffix}`);","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/Egonex-AI/Understand-Anything/blob/07edf82a04371b6f69779b067bdc8a1a8753a9db/understand-anything-plugin/skills/understand/prepare-incremental.mjs#L505-L541","documentation":"When the existing snapshot's baseCommit does not match the requested baseCommit (or no snapshot graph exists), main falls back to using the graph produced in this run as the baseline. If that graph records a gitCommitHash different from the requested baseCommit, there is no symbol baseline for the requested base, and retrying incrementally could silently protect symbols against the wrong revision — so it refuses.","triggerScenarios":"existingSnapshot.baseCommit !== baseCommit and the freshly produced graph.project.gitCommitHash differs from the requested baseCommit — e.g. passing a baseCommit other than the one the previous full analysis was built from, or HEAD moved between graph generation and this run.","commonSituations":"Requesting an older baseCommit than the last full analysis used, a rebase/reset changing HEAD after the graph was built, or a stale .ua/knowledge-graph.json generated at a different commit.","solutions":["Pass the baseCommit that matches the previous analysis: read .ua snapshot's baseCommit and use it","Re-run a full /understand analysis at the desired base commit to regenerate a matching graph, then retry incremental","Update the repo so HEAD/gitCommitHash matches the requested baseCommit (git checkout <baseCommit>)","Delete stale snapshot files under .ua/ and rebuild from a full analysis if the history was rewritten (rebase/reset)"],"exampleFix":"// before\nnode prepare-incremental.mjs . abc1234   # graph built at different commit\n// after\n# rebuild the baseline at the requested commit\ngit checkout abc1234\nunderstand --full\nnode prepare-incremental.mjs . abc1234","handlingStrategy":"validation","validationCode":"const snapshot = JSON.parse(fs.readFileSync('.ua/base-snapshot.json', 'utf8'));\nconst graph = JSON.parse(fs.readFileSync('.ua/knowledge-graph.json', 'utf8'));\nif (snapshot.baseCommit !== requestedBase || graph?.project?.gitCommitHash !== requestedBase) {\n  console.error('Baseline commit mismatch; run a full analysis at the requested base first');\n}","typeGuard":"function baselineMatches(snapshot, graph, base) {\n  return snapshot?.baseCommit === base &&\n    (!graph?.project?.gitCommitHash || graph.project.gitCommitHash === base);\n}","tryCatchPattern":"try {\n  await prepareIncremental(args);\n} catch (err) {\n  if (err.message.includes('cannot safely retry')) {\n    console.error('Rebuilding baseline with full analysis at the requested commit');\n    return runFullAnalysis(base);\n  }\n  throw err;\n}","preventionTips":["Always pass the same baseCommit the previous full analysis was built at","Avoid rebases/resets that move HEAD after generating the graph, or rebuild the graph afterwards","Check graph.project.gitCommitHash against your intended baseCommit before incremental runs"],"tags":["git","state","incremental-analysis"],"backgroundTag":"invalid-state-transition","analyzedSha":"07edf82a04371b6f69779b067bdc8a1a8753a9db","analyzedAt":"2026-09-07T23:20:10.829Z","contentChangedAt":"2026-09-07T23:20:10.829Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}