{"record":{"id":"6c1ba5c3fc16e974","repo":"abhigyanpatwari/GitNexus","slug":"embedding-generation-completed-without-persisted-e","errorCode":null,"errorMessage":"Embedding generation completed without persisted embeddings. The index was not registered to avoid silently reporting embeddings: 0. Check the embedding endpoint/model configuration (GITNEXUS_EMBEDDING_URL / GITNEXUS_EMBEDDING_MODEL) and re-run `gitnexus analyze --embeddings`; the graph itself is unaffected, so `--drop-embeddings` indexes without them.","messagePattern":"Embedding generation completed without persisted embeddings\\. The index was not registered to avoid silently reporting embeddings: 0\\. Check the embedding endpoint/model configuration \\(GITNEXUS_EMBEDDING_URL / GITNEXUS_EMBEDDING_MODEL\\) and re-run `gitnexus analyze --embeddings`; the graph itself is unaffected, so `--drop-embeddings` indexes without them\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/run-analyze.ts","lineNumber":3333,"sourceCode":"    //   1. the pipeline never ran (cap-skipped / not requested) —\n    //      `embeddingSkipped`, still short-circuited;\n    //   2. the pipeline ran but had NOTHING to embed (totalNodes 0 after the\n    //      incremental filter — e.g. a resume whose pending sweep deleted the\n    //      last rows) over a legitimately empty table;\n    //   3. the count query failed or answered non-numerically (above) — a\n    //      diagnostic failure, not an indexing failure;\n    //   4. the pipeline embedded and NOTHING persisted — the real defect.\n    // Only (4) throws. `attemptedEmbedding` is what separates it from (2):\n    // `nodesProcessed` is now the REAL completed-node count and\n    // `failedNodeIds` names the nodes whose rows were dropped, so\n    // \"attempted\" ≡ at least one node was walked to a conclusion.\n    const attemptedEmbedding =\n      !embeddingSkipped &&\n      embeddingResult !== undefined &&\n      (embeddingResult.nodesProcessed > 0 || embeddingResult.failedNodeIds.length > 0);\n\n    if (attemptedEmbedding && stats.nodes > 0 && embeddingCount === 0) {\n      throw new Error(\n        'Embedding generation completed without persisted embeddings. ' +\n          'The index was not registered to avoid silently reporting embeddings: 0. ' +\n          'Check the embedding endpoint/model configuration (GITNEXUS_EMBEDDING_URL / ' +\n          'GITNEXUS_EMBEDDING_MODEL) and re-run `gitnexus analyze --embeddings`; ' +\n          'the graph itself is unaffected, so `--drop-embeddings` indexes without them.',\n      );\n    }\n\n    if (embeddingCount === undefined) {\n      log(\n        'Warning: registering the index without a verified embedding count — the count query ' +\n          'did not answer, so stats.embeddings falls back to the last known value. ' +\n          'Re-run `gitnexus analyze --embeddings` if semantic search comes back empty.',\n      );\n    }\n\n    // ── An unverifiable count must leave a way back (#2790) ───────────────\n    // The carry-forward below is a GUESS, and the guess is load-bearing (see","sourceCodeStart":3315,"sourceCodeEnd":3351,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/run-analyze.ts#L3315-L3351","documentation":"Thrown at the Phase 5 embedding gate when the embedding pipeline processed nodes (`attemptedEmbedding` is true: `nodesProcessed > 0` or `failedNodeIds.length > 0`), the graph has nodes (`stats.nodes > 0`), but the persisted embedding count is exactly zero. This is case (4) of four formerly-collapsed states: the pipeline ran and wrote nothing — a genuine defect, not a skip, an empty table, or a count-query failure. The index is deliberately not registered to avoid silently reporting `embeddings: 0`.","triggerScenarios":"`attemptedEmbedding && stats.nodes > 0 && embeddingCount === 0`. The embedding endpoint accepted requests (or returned structured failures) but no rows were persisted to the embedding table. Typically the endpoint URL is wrong (200 HTML from a reverse proxy instead of an embedding API), the model name is invalid (endpoint returns an error for every node), or the embedding write path silently dropped all rows.","commonSituations":"`GITNEXUS_EMBEDDING_URL` points to a base URL that isn't an embeddings endpoint (e.g., points to the chat completions endpoint, or a login page); `GITNEXUS_EMBEDDING_MODEL` is not a valid model for the provider; the endpoint returns vectors in an unexpected format that the adapter rejects for every node; a network proxy strips or mangles the response body.","solutions":["Verify `GITNEXUS_EMBEDDING_URL` points to the correct embeddings endpoint (e.g., `https://api.openai.com/v1/embeddings`, not `/v1/chat/completions`).","Verify `GITNEXUS_EMBEDDING_MODEL` is a valid embedding model name for your provider.","Test the endpoint manually with `curl` to confirm it returns embedding vectors for a sample input.","Re-run `gitnexus analyze --embeddings` once the configuration is fixed.","If you need the index without embeddings for now, run `gitnexus analyze --drop-embeddings` (the graph itself is unaffected)."],"exampleFix":"// before\nexport GITNEXUS_EMBEDDING_URL=https://api.openai.com/v1/chat/completions  # wrong endpoint\ngitnexus analyze --embeddings\n// error: Embedding generation completed without persisted embeddings.\n// after\nexport GITNEXUS_EMBEDDING_URL=https://api.openai.com/v1/embeddings  # correct endpoint\ngitnexus analyze --embeddings","handlingStrategy":"validation","validationCode":"// Before analyze --embeddings, verify the endpoint returns vectors:\n// (Quick smoke test of the embedding endpoint)\nimport { validateEmbeddingEndpoint } from './embeddings/endpoint-check.js';\nconst ok = await validateEmbeddingEndpoint(\n  process.env.GITNEXUS_EMBEDDING_URL!,\n  process.env.GITNEXUS_EMBEDDING_MODEL!,\n);\nif (!ok) {\n  console.error('Embedding endpoint did not return valid vectors. Check URL and MODEL.');\n  process.exit(1);\n}","typeGuard":"const isLikelyEmbeddingsEndpoint = (url: string): boolean =>\n  /\\/embeddings?$/.test(url) || /embedding/i.test(url);","tryCatchPattern":"try {\n  await runAnalyze({ ...options, embeddings: true });\n} catch (err) {\n  if (err instanceof Error && err.message.includes('completed without persisted embeddings')) {\n    console.error('Check GITNEXUS_EMBEDDING_URL and GITNEXUS_EMBEDDING_MODEL. Test with curl first.');\n    console.error('Run `gitnexus analyze --drop-embeddings` to index without embeddings for now.');\n  }\n  throw err;\n}","preventionTips":["Smoke-test the embedding endpoint with `curl` before running `--embeddings` on a large repo.","Verify `GITNEXUS_EMBEDDING_URL` ends with the embeddings path (e.g., `/v1/embeddings`), not chat/completions.","Pin embedding model names in config to avoid silent endpoint API changes."],"tags":["embeddings","configuration","endpoint","analyze"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}