{"record":{"id":"94f537729e675d82","repo":"abhigyanpatwari/GitNexus","slug":"embed-could-not-count-persisted-embeddings-leav","errorCode":null,"errorMessage":"[embed] could not count persisted embeddings; leaving stats.embeddings untouched","messagePattern":"\\[embed\\] could not count persisted embeddings; leaving stats\\.embeddings untouched","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"gitnexus/src/server/api.ts","lineNumber":1797,"sourceCode":"                      embeddingIdentity,\n                      checkpoint,\n                      pendingNodeIds,\n                    ),\n                  },\n                  embeddings,\n                );\n                await saveMeta(entry.storagePath, embeddingMeta);\n              };\n              /**\n               * Count the persisted rows, or report the answer never arrived.\n               * The TRI-STATE is carried to the fold rather than collapsed here:\n               * `unknown` is not 0, and only the fold knows what to carry\n               * forward instead (core/embedding-count.ts).\n               */\n              const countPersistedEmbeddings = async (): Promise<PersistedEmbeddingCount> => {\n                const counted = await measurePersistedEmbeddingCount(executeQuery);\n                if (counted.kind === 'unknown') {\n                  logger.warn(\n                    { reason: counted.reason },\n                    '[embed] could not count persisted embeddings; leaving stats.embeddings untouched',\n                  );\n                }\n                return counted;\n              };\n              // Fetch existing content hashes for incremental embedding.\n              // Delegated to lbug-adapter which owns the DB query logic and legacy-fallback handling.\n              const { fetchExistingEmbeddingHashes } = await import('../core/lbug/lbug-adapter.js');\n              const existingEmbeddings = await fetchExistingEmbeddingHashes(executeQuery);\n              if (existingEmbeddings && existingEmbeddings.size > 0) {\n                console.log(\n                  `[embed] ${existingEmbeddings.size} nodes already embedded — incremental run with content-hash comparison`,\n                );\n              }\n              const pipelineResult = await runEmbeddingPipeline(\n                executeQuery,\n                executeWithReusedStatement,","sourceCodeStart":1779,"sourceCodeEnd":1815,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/aac7515d2a8c50a1f8f923c6fb77218b333560d6/gitnexus/src/server/api.ts#L1779-L1815","documentation":"After persisting embeddings, the server counts persisted rows via measurePersistedEmbeddingCount. The count is a tri-state; when it returns kind 'unknown' (the counting query itself failed), this warning fires and stats.embeddings is deliberately left untouched rather than set to 0: unknown is not 0, and only the fold in core/embedding-count.ts decides what to carry forward. The embeddings themselves were persisted; only the statistic is in doubt.","triggerScenarios":"An embed/analyze run with embeddings enabled where the count query against the LadybugDB store fails: transient query error, DB file lock held by a concurrent process, or a degraded read. The warning carries the failure reason from the tri-state result.","commonSituations":"Concurrent GitNexus processes contending on the LadybugDB file (its file locking is known to be finicky in containers); transient I/O errors; the displayed embedding count then reflects the previous value instead of the rows just written.","solutions":["No data was lost: the embeddings persisted, only the count is stale and carried forward by the fold","Re-run the embed step once the DB is uncontended to refresh the count","Stop overlapping schedules so embed and analyze do not run against the same storage concurrently","If it recurs, inspect the reason field in the warning to separate lock contention from real I/O failure"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const counted = await measurePersistedEmbeddingCount(executeQuery);\n// never treat unknown as 0 — carry the previous stat forward instead\nstats.embeddings = counted.kind === 'unknown'\n  ? previousStats.embeddings\n  : counted.value;","typeGuard":"type PersistedEmbeddingCount =\n  | { kind: 'count'; value: number }\n  | { kind: 'unknown'; reason: string };\n\nfunction isUnknownCount(\n  c: PersistedEmbeddingCount,\n): c is { kind: 'unknown'; reason: string } {\n  return c.kind === 'unknown';\n}","tryCatchPattern":null,"preventionTips":["Never render an unknown count as 0 in downstream UI","Avoid concurrent DB writers against the same storage during embed","Log counted.reason — it separates lock contention from real I/O failure"],"tags":["embeddings","stats","ladybugdb","tri-state","database"],"backgroundTag":"database-query-failed","analyzedSha":"aac7515d2a8c50a1f8f923c6fb77218b333560d6","analyzedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-08-31T04:17:50.494Z"}