abhigyanpatwari/GitNexus · warning

GitNexus: BM25/FTS search failed (FTS indexes may not exist)

Error message

GitNexus: BM25/FTS search failed (FTS indexes may not exist) — falling back to semantic-only

What it means

searchFTSFromLbug(query, limit, repo.lbugPath) threw after the module imported fine. The most common cause is simply an un-indexed FTS extension — a normal configuration — so it is swallowed as a graceful degrade to semantic-only with ftsUsed:false, logged at warn (never error) to match the sibling import-failure fallback and avoid false alarms.

Source

Thrown at gitnexus/src/mcp/local/local-backend.ts:3095

      ({ searchFTSFromLbug } = await import('../../core/search/bm25-index.js'));
    } catch (err: any) {
      // Module import can fail in sandboxed MCP contexts (#1489)
      logger.warn(
        { err: err?.message },
        'GitNexus: bm25-index.js import failed — falling back to semantic-only',
      );
      return { results: [], ftsUsed: false };
    }
    let ftsResponse;
    try {
      ftsResponse = await searchFTSFromLbug(query, limit, repo.lbugPath);
    } catch (err: any) {
      // Swallowed, gracefully-degraded failure: the search falls back to
      // semantic-only (a valid result), and the most common cause is simply an
      // un-indexed FTS extension — a normal configuration, not an operation
      // error. Logged at warn (matching the sibling import-failure fallback
      // above), never error, so it does not raise a false alarm.
      logger.warn(
        { err: err.message },
        'GitNexus: BM25/FTS search failed (FTS indexes may not exist) — falling back to semantic-only',
      );
      return { results: [], ftsUsed: false };
    }

    // Guard against unexpected response shape (#1489) — ftsResponse.results
    // could be undefined when the FTS extension is unavailable in the MCP process.
    const bm25Results = ftsResponse?.results ?? [];
    const ftsUsed = ftsResponse?.ftsAvailable ?? false;
    const nonBenignErrors = ftsResponse?.nonBenignErrors;

    const results: any[] = [];

    for (const bm25Result of bm25Results) {
      const fullPath = bm25Result.filePath;
      try {
        // Prefer direct nodeId lookup (exact FTS-matched nodes) over filePath fallback.

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Re-run `gitnexus analyze` so FTS indexes are (re)built for the DB.
  2. Verify the LadybugDB build in use includes the FTS extension (reinstall the package to get the matching prebuild).
  3. Treat results as semantic-only meanwhile — the response's ftsUsed flag tells you BM25 contributed nothing.
  4. Check the logged err message: anything beyond a missing-index/binder error indicates a real fault worth fixing.
Defensive patterns

Strategy: fallback

Validate before calling

// Before searching: confirm FTS exists for this repo's DB
const probe = await searchFTSFromLbug('__probe__', 1, repo.lbugPath);
if (!probe.ftsAvailable) flagSemanticOnly(repo); // expected warn avoided, behavior unchanged

Try / catch

try {
  ftsResponse = await searchFTSFromLbug(query, limit, repo.lbugPath);
} catch (err) {
  logger.warn({ err: err.message }, 'falling back to semantic-only');
  return { results: [], ftsUsed: false };
}

Prevention

When it happens

Trigger: BM25 search runs against a repo whose LadybugDB has no FTS indexes (index built without FTS, or the FTS extension unavailable in the MCP process); the query call then throws instead of returning an empty ftsAvailable:false response.

Common situations: Repos analyzed by versions/configurations that skip FTS creation; MCP processes loading a LadybugDB build without the FTS extension; fresh DBs queried before a completed analyze.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20). Data as JSON: /api/errors/56872281a0fd2ef8. Report an issue: GitHub.