{"record":{"id":"1f3ae3db6f666846","repo":"abhigyanpatwari/GitNexus","slug":"batch-execution-failed-for-rows-firstrow-1","errorCode":null,"errorMessage":"Batch execution failed for rows ${firstRow + 1}-${firstRow + subBatch.length}: ${msg} (${queryPreview})","messagePattern":"Batch execution failed for rows (.+?)-(.+?): (.+?) \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/lbug/lbug-adapter.ts","lineNumber":1835,"sourceCode":"    const firstRow = subBatchIndex * SUB_BATCH_SIZE;\n    // One critical section per sub-batch: the prepare + its executes run with\n    // exclusive access to the connection (so the WAL checkpoint driver cannot\n    // interleave a CHECKPOINT mid-batch), while the lock is released between\n    // sub-batches to let the driver checkpoint during a long writeback.\n    await withConnLock(async () => {\n      const stmt = await c.prepare(cypher);\n      if (!stmt.isSuccess()) {\n        const errMsg = await stmt.getErrorMessage();\n        throw new Error(`Prepare failed: ${errMsg}`);\n      }\n      try {\n        for (const params of subBatch) {\n          await drainQueryResult(await c.execute(stmt, params));\n        }\n      } catch (e) {\n        const msg = e instanceof Error ? e.message : String(e);\n        const queryPreview = cypher.replace(/\\s+/g, ' ').slice(0, 120);\n        throw new Error(\n          `Batch execution failed for rows ${firstRow + 1}-${firstRow + subBatch.length}: ${msg} (${queryPreview})`,\n        );\n      }\n      // Note: LadybugDB PreparedStatement doesn't require explicit close()\n    });\n  }\n};\n\n/**\n * Node and edge totals for the open index.\n *\n * `edges` is `undefined` when the count could NOT BE TAKEN, and that is a\n * different fact from zero. It used to be initialised to 0 with the query in a\n * swallowing `catch`, so a WAL/lock contention throw during finalize — a\n * documented hazard on this exact call — returned a measured-looking 0. The\n * collapse check downstream then read a perfectly healthy index as a total\n * write collapse, which is precisely the confident-zero failure that check\n * exists to prevent.","sourceCodeStart":1817,"sourceCodeEnd":1853,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/lbug/lbug-adapter.ts#L1817-L1853","documentation":"Thrown during LadybugDB batch writeback when executing a prepared statement across a sub-batch of parameter rows (SUB_BATCH_SIZE=4) fails mid-flight. The error wraps the underlying LadybugDB execute failure with the row range, the original error message, and a 120-char preview of the Cypher query. This is a write-path error: the writeback pipeline uses batched parameterized INSERTs to populate graph nodes/edges, and any per-row execution failure (constraint violation, type mismatch, native crash) aborts the entire sub-batch.","triggerScenarios":"Calling the internal batch-insert function (which wraps c.prepare + c.execute in a withConnLock critical section) with a paramsList where one or more parameter objects contain values incompatible with the prepared Cypher schema — e.g. a null where the column requires a non-null, a string where INT32 is expected, or a parameter key that doesn't exist in the Cypher placeholder set. Also triggered by native LadybugDB runtime exceptions during execute(): buffer manager exhaustion, WAL write failure under disk pressure, or a closed/invalidated connection.","commonSituations":"A schema change in GitNexus core that adds a new node property but the writeback code hasn't been updated to supply it; a very large paramsList where one row has malformed data extracted from an exotic source file; disk-full conditions during incremental re-writeback where the WAL can't grow; concurrent process holding a write lock that causes execute to fail; running on LadybugDB 0.18.0 where a type coercion edge case rejects certain parameter shapes.","solutions":["Read the wrapped `msg` and `queryPreview` in the error — the underlying LadybugDB message pinpoints whether it's a type error, constraint violation, or IO failure","If the error is IO-related (disk full, WAL write failure), free disk space and re-run `gitnexus analyze` — the writeback is transactional and a failed sub-batch leaves the incremental dirty flag set, triggering a full rebuild on next run","If the error is a type/schema mismatch, check the node/edge property types in `schema.ts` against the parameter objects being passed — ensure all Cypher placeholders ($name) have matching keys in every params object","If a specific row's data is the cause, inspect the source extraction for the failing row range (firstRow+1 to firstRow+subBatch.length) to find the malformed symbol/file","Re-run `gitnexus analyze` after fixing the root cause — the crash-recovery dirty flag forces a clean full rebuild"],"exampleFix":"// before — params object missing a required key or wrong type\nconst params = { name: symbol.name };\n// after — supply all placeholders with correct types\nconst params = { name: symbol.name, kind: symbol.kind, filePath: symbol.filePath, line: Number(symbol.line) };","handlingStrategy":"try-catch","validationCode":"// Validate all parameter objects before batch insert\nfunction validateBatchParams(paramsList: Record<string, unknown>[], requiredKeys: string[]): void {\n  for (let i = 0; i < paramsList.length; i++) {\n    for (const key of requiredKeys) {\n      if (!(key in paramsList[i])) {\n        throw new Error(`Row ${i}: missing required parameter key \"${key}\"`);\n      }\n    }\n  }\n}","typeGuard":"function isValidBatchParams(params: unknown, requiredKeys: readonly string[]): params is Record<string, unknown> {\n  if (typeof params !== 'object' || params === null) return false;\n  const obj = params as Record<string, unknown>;\n  return requiredKeys.every((k) => k in obj);\n}","tryCatchPattern":"try {\n  await batchExecuteWithConnLock(cypher, paramsList);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Batch execution failed')) {\n    // Parse row range from message, log the specific failing batch\n    logger.error(`Writeback batch failed — dirty flag set, next run will full-rebuild`, e);\n  }\n  throw e; // Re-throw: the caller's crash-recovery must set the dirty flag\n}","preventionTips":["Always validate parameter object keys against the Cypher placeholder set before calling batch insert","Use TypeScript types to enforce parameter object shapes at compile time","Run `gitnexus analyze` in a CI pipeline after schema changes to catch type mismatches early","Monitor disk space before starting large writebacks to prevent IO failures mid-batch"],"tags":["ladybugdb","writeback","batch-insert","cypher","graph-store"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}