{"record":{"id":"374d321c9a967abb","repo":"abhigyanpatwari/GitNexus","slug":"bridge-query-returned-an-empty-queryresult-array","errorCode":null,"errorMessage":"Bridge query returned an empty QueryResult array","messagePattern":"Bridge query returned an empty QueryResult array","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/group/bridge-db.ts","lineNumber":590,"sourceCode":"  // are single-threaded — they're absent from bridgeEntryByHandle and skip the\n  // lock at zero cost.\n  const entry = bridgeEntryByHandle.get(handle);\n  return entry ? withHandleLock(entry, run) : run();\n}\n\n/**\n * LadybugDB's `conn.query` / `conn.execute` can return either a single\n * `QueryResult` (for a single statement) or an array of them (when a\n * multi-statement script is dispatched). We always pass a single statement,\n * so the array form is a wrapper we unwrap here — but an empty top-level\n * array would cause `.getAll()` on `undefined` and crash with a confusing\n * stack. Throwing an explicit error makes a driver-contract regression\n * visible immediately instead of masking it.\n */\nfunction unwrapQueryResult(queryResult: lbug.QueryResult | lbug.QueryResult[]): lbug.QueryResult {\n  if (Array.isArray(queryResult)) {\n    if (queryResult.length === 0) {\n      throw new Error('Bridge query returned an empty QueryResult array');\n    }\n    return queryResult[0];\n  }\n  return queryResult;\n}\n\n/**\n * Release a caller's reference to a bridge handle.\n *\n * - **Cache-owned handle** (returned by `getCachedBridgeReadOnly`): this is the\n *   matching *release* for that acquire — it decrements the lease refcount, it\n *   does NOT close the native handle. The cache owns the lifetime; the handle\n *   closes on explicit `invalidateBridgeCache`, mtime-eviction, or process\n *   shutdown. If the entry was already evicted and this is the last lease, the\n *   deferred native close fires here (exactly once).\n * - **Uncached/writable handle** (e.g. the `writeBridge` temp DB): closes the\n *   native handle for real (CHECKPOINT-flush for writable handles).\n *","sourceCodeStart":572,"sourceCodeEnd":608,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/group/bridge-db.ts#L572-L608","documentation":"Thrown by the private unwrapQueryResult helper when LadybugDB's conn.query/conn.execute returns an array of QueryResult objects that is empty. GitNexus always dispatches a single statement, so a top-level empty array is a driver-contract regression, not normal output. The explicit throw prevents a downstream `.getAll()` on undefined producing a confusing stack.","triggerScenarios":"Any code path through queryBridge or writeBridge where the LadybugDB driver returns [] instead of a single QueryResult — e.g. a future driver version changing multi-statement handling, or a monkeypatched/mock connection returning the wrong shape in tests.","commonSituations":"LadybugDB driver upgraded to a version that returns [] for certain DDL or no-op statements; a test stub mocking conn.query with an empty array; a corrupted connection returning an unexpected response shape after a native crash.","solutions":["Check the LadybugDB driver version in use — if it was recently bumped, compare its QueryResult contract against the version GitNexus was written for.","If this reproduces in tests, fix the mock/stub to return a single QueryResult object (or a one-element array), not [].","If it reproduces against a real bridge DB, capture the exact cypher and params and file a driver-contract regression with the LadybugDB maintainers.","As a last resort, rebuild the bridge DB from scratch (the on-disk bridge.lbug may be in a corrupted state)."],"exampleFix":"// test stub returning the wrong shape — triggers the guard\nmockConn.query = async () => [];\n\n// after — single QueryResult object as the contract expects\nmockConn.query = async () => ({ getAll: async () => [], close: async () => {} });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// unwrapQueryResult's empty-array throw indicates a driver regression.\n// Catch and report, but treat as a bug to investigate, not a normal runtime path.\ntry {\n  const rows = await queryBridge<T>(handle, cypher);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Bridge query returned an empty QueryResult array') {\n    logger.error({ cypher }, 'LadybugDB driver-contract regression: empty QueryResult array');\n  }\n  throw err;\n}","preventionTips":["When mocking LadybugDB in tests, return a single QueryResult object (or a one-element array) — never [].","Pin the LadybugDB driver version; re-run the bridge suite when upgrading.","If you maintain a custom connection wrapper, ensure it never returns [] for single-statement queries."],"tags":["ladybugdb","driver-contract","group-bridge","defensive-guard"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}