{"record":{"id":"b973c68114516774","repo":"abhigyanpatwari/GitNexus","slug":"fts-repair-failed-missing-indexes-after-rebuild","errorCode":null,"errorMessage":"FTS repair failed - missing indexes after rebuild: ${missing.join(', ')}.${reasons} Run `gitnexus analyze --force` to perform a full graph+FTS rebuild; if that also fails, verify FTS extension availability via `gitnexus doctor`.","messagePattern":"FTS repair failed - missing indexes after rebuild: (.+?)\\.(.+?) Run `gitnexus analyze --force` to perform a full graph\\+FTS rebuild; if that also fails, verify FTS extension availability via `gitnexus doctor`\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/run-analyze.ts","lineNumber":1217,"sourceCode":"      const repairFailures = await createSearchFTSIndexes({\n        onIndexStart: options.verbose\n          ? (table, indexName) => log(`FTS: creating ${table}.${indexName}`)\n          : undefined,\n        onIndexReady: options.verbose\n          ? (table, indexName) => log(`FTS: ready ${table}.${indexName}`)\n          : undefined,\n      });\n      const missing = await verifySearchFTSIndexes(executeQuery);\n      if (missing.length > 0) {\n        // #2889: name WHY each index is missing when the build itself said so.\n        // Repair now rebuilds every table it can before reporting, so the tables\n        // absent from this list were genuinely repaired even on a failed run —\n        // previously the first failure aborted the sweep and the message could\n        // only ever list \"missing\", never a reason. Same sentence the analyze\n        // degrade path prints, so one failure does not read two ways.\n        const reasons =\n          repairFailures.length > 0 ? ` ${summarizeFtsIndexBuildFailures(repairFailures)}.` : '';\n        throw new Error(\n          `FTS repair failed - missing indexes after rebuild: ${missing.join(', ')}.${reasons} ` +\n            'Run `gitnexus analyze --force` to perform a full graph+FTS rebuild; ' +\n            'if that also fails, verify FTS extension availability via `gitnexus doctor`.',\n        );\n      }\n      await ensureGitNexusIgnored(repoPath);\n      // #2767: stamp ONLY capabilities.fts so a long-lived MCP session's\n      // ensureInitialized() has an explicit, correctly-scoped signal that FTS\n      // changed — indexedAt/lastCommit/runnerIdentity/stats are copied through\n      // untouched (see the \"must not claim a new analyzer identity\" comment\n      // below). capabilities is forensic/no-programmatic-readers-until-now, so\n      // graph/vectorSearch are backfilled with conservative, honest defaults\n      // when a legacy meta.json predates this field entirely — repair-fts\n      // never touched them and cannot claim a capability it did not verify.\n      // Best-effort: a write failure must not turn an already-successful FTS\n      // rebuild into a reported repair failure.\n      try {\n        // Re-read the on-disk meta immediately before writing, rather than","sourceCodeStart":1199,"sourceCodeEnd":1235,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/run-analyze.ts#L1199-L1235","documentation":"Thrown after `--repair-fts` ran `createSearchFTSIndexes` and then `verifySearchFTSIndexes` still found indexes missing. The repair sweep now rebuilds every table it can before reporting, so the message includes per-index build-failure reasons (via `summarizeFtsIndexBuildFailures`) when `repairFailures` is non-empty. This distinguishes 'the rebuild itself reported why it failed' from a silent absence.","triggerScenarios":"`verifySearchFTSIndexes(executeQuery)` returns a non-empty `missing` array after `createSearchFTSIndexes` completed (possibly with partial failures). The FTS extension loaded but one or more `CREATE_FTS_INDEX` operations did not produce a usable index.","commonSituations":"A LadybugDB FTS schema mismatch after a version bump; a corrupt or nearly-full disk where the index creation partially succeeds; a tokenizer/stemmer value the installed extension rejects (validation passed but CREATE fails); a race where the DB was checkpointed mid-create.","solutions":["Run `gitnexus analyze --force` for a full graph + FTS rebuild from scratch.","If `--force` also fails, run `gitnexus doctor` to verify the FTS extension is healthy.","Check available disk space — FTS index creation needs temporary space proportional to indexed content.","If the build-failure reasons mention a specific stemmer/tokenizer, verify `GITNEXUS_FTS_STEMMER` is set to a value the installed extension supports."],"exampleFix":"// before\ngitnexus analyze --repair-fts\n// error: FTS repair failed - missing indexes after rebuild: ...\n// after\ngitnexus analyze --force  // full rebuild of graph + FTS\ngitnexus doctor           // verify FTS extension health","handlingStrategy":"try-catch","validationCode":"// After repair, verify indexes before reporting success (the repair path already does this internally):\nimport { verifySearchFTSIndexes } from './search/fts-indexes.js';\nconst missing = await verifySearchFTSIndexes(executeQuery);\nif (missing.length > 0) {\n  console.error(`Still missing: ${missing.join(', ')}. Run 'gitnexus analyze --force'.`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await runAnalyze({ ...options, repairFts: true });\n} catch (err) {\n  if (err instanceof Error && err.message.includes('missing indexes after rebuild')) {\n    console.error('Run `gitnexus analyze --force` for a full graph+FTS rebuild.');\n  }\n  throw err;\n}","preventionTips":["Keep the LadybugDB FTS extension version aligned with the GitNexus version to avoid schema mismatches.","Ensure adequate disk space before running analyze — FTS creation is space-intensive.","Run `gitnexus doctor` periodically to catch extension health issues early."],"tags":["fts","analyze","rebuild","index-verification"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}