{"record":{"id":"071c02b0ad7f3bf6","repo":"abhigyanpatwari/GitNexus","slug":"gitnexus-query-failed-degraded","errorCode":null,"errorMessage":"GitNexus query failed (degraded)","messagePattern":"GitNexus query failed \\(degraded\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"gitnexus/src/mcp/local/local-backend.ts","lineNumber":557,"sourceCode":" *\n * `error` is intentionally NOT used here — it is reserved for failures that\n * actually abort an operation, which log directly rather than through this\n * best-effort-degradation helper.\n *\n * Contract for callers (#2283 review): only route a failure here when the\n * caller ALSO surfaces the degradation in its result (a `partial` flag,\n * `failed_files`, `traversalComplete:false`, …). A mutating or safety-critical\n * path that would otherwise report success/clean (e.g. `rename` apply, the\n * `detect_changes` safety gate) MUST set that result-level signal — `warn`\n * alone is not a substitute for an honest result.\n */\nfunction logQueryError(context: string, err: unknown): void {\n  const msg = err instanceof Error ? err.message : String(err);\n  if (isBenignMissingTableError(err)) {\n    logger.debug({ context, err: msg }, 'GitNexus query skipped (missing optional data)');\n    return;\n  }\n  logger.warn({ context, err: msg }, 'GitNexus query failed (degraded)');\n}\n\n/**\n * A \"missing table/label/relation\" prepare error is benign for the query tool's\n * best-effort enrichment: a repo analyzed without processes or communities simply\n * has no `Process`/`Community` tables, so the `STEP_IN_PROCESS` / `MEMBER_OF`\n * enrichment queries fail to prepare. That is a normal configuration, NOT a\n * degraded result — it must not raise the `partial` flag (which callers would\n * then learn to ignore). Real failures (timeouts, locks, native faults) do.\n */\nfunction isBenignMissingTableError(err: unknown): boolean {\n  const msg = err instanceof Error ? err.message : String(err ?? '');\n  // The `not (defined|found)` arm is scoped to a schema object (table/label/\n  // rel/column/property), mirroring lbug-adapter's isMissingColumnError\n  // (`/(table|column|property).*not found/i`): an unscoped \"not found\" matched\n  // operation failures like `rg: not found` (ripgrep absent) or `Symbol not\n  // found`, which this helper would then silently demote to `debug` (#2283).\n  return /does not exist|no such (table|label|rel)|unknown (table|label)|(table|label|rel|column|property)[^\\n]*\\bnot (defined|found)\\b/i.test(","sourceCodeStart":539,"sourceCodeEnd":575,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/aac7515d2a8c50a1f8f923c6fb77218b333560d6/gitnexus/src/mcp/local/local-backend.ts#L539-L575","documentation":"logQueryError is the MCP local backend's best-effort enrichment error funnel: a query failed non-benignly (timeouts, locks, native faults) and is logged at warn as 'degraded' — benign missing-table errors (repo analyzed without Process/Community tables) are demoted to debug. The doc comment on the helper is the contract: warn alone is not enough; mutating or safety-critical callers MUST also set a result-level signal (partial flag, failed_files, traversalComplete:false).","triggerScenarios":"Any query tool enrichment sub-query throws something isBenignMissingTableError does not match: DB lock timeouts while serve/analyze run concurrently, engine native faults, corrupted tables. The surrounding tool still returns results but must carry the degradation signal for those specific paths.","commonSituations":"Querying an index while analyze is rewriting it; querying a repo indexed by a much older version (schema drift beyond the benign patterns); partial/corrupt DBs after disk issues.","solutions":["Check whether the result carries partial/failed_files/traversalComplete signals and treat it as degraded rather than clean.","Let the concurrent analyze finish (or re-run it) and retry the query.","Re-index if the index is old relative to the server version: `gitnexus analyze`.","If the err in the log line is a lock/busy message, serialize access to the DB."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isBenignMissingTableError(err: unknown): boolean {\n  const msg = err instanceof Error ? err.message : String(err ?? '');\n  return /does not exist|Table: .* not found/i.test(msg);\n}","tryCatchPattern":"// Mirror the backend's own funnel: demote benign, escalate real, AND set result signals\ntry {\n  results = await enrich(queryResult);\n} catch (err) {\n  if (isBenignMissingTableError(err)) logger.debug({ err });\n  else { logger.warn({ err }, 'degraded'); result.partial = true; }\n}","preventionTips":["Never rely on the warn alone — check partial / failed_files / traversalComplete on results.","Keep query traffic and analyze writes serialized per DB.","Re-index after version upgrades so enrichment tables exist and benign misses shrink."],"tags":["mcp","query","degraded","best-effort","ladybugdb"],"backgroundTag":"query-degraded","analyzedSha":"aac7515d2a8c50a1f8f923c6fb77218b333560d6","analyzedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-08-31T04:17:50.494Z"}