{"record":{"id":"b79ee6837fbf4f46","repo":"abhigyanpatwari/GitNexus","slug":"repository-metadata-is-missing-run-gitnexus-analy","errorCode":null,"errorMessage":"Repository metadata is missing; run gitnexus analyze first","messagePattern":"Repository metadata is missing; run gitnexus analyze first","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/server/api.ts","lineNumber":1769,"sourceCode":"          }\n        }, EMBED_TIMEOUT_MS);\n\n        // Run embedding pipeline asynchronously\n        (async () => {\n          // Set inside withLbugDb, read after it closes (#2790).\n          let partialRunError: string | undefined;\n          let partialRunDetail: AnalyzeJobPartialOutcome | undefined;\n          try {\n            const lbugPath = path.join(entry.storagePath, 'lbug');\n            await withLbugDb(lbugPath, async () => {\n              const { runEmbeddingPipeline } =\n                await import('../core/embeddings/embedding-pipeline.js');\n              const { resolveEmbeddingIdentity } =\n                await import('../core/embeddings/embedding-identity.js');\n              const embeddingIdentity = resolveEmbeddingIdentity();\n              let embeddingMeta = await loadMeta(entry.storagePath);\n              if (!embeddingMeta) {\n                throw new Error('Repository metadata is missing; run gitnexus analyze first');\n              }\n              const priorCheckpoint = embeddingMeta.embeddingCheckpoint;\n              // The SAME decision the CLI's resume gate makes\n              // (core/embedding-checkpoint.ts). This route used to hard-throw on\n              // any identity mismatch and ignore `attempts` entirely, so a\n              // `'partial'` marker written by `gitnexus analyze` and resumed\n              // here hit exactly the permanent wedge `kind` exists to remove:\n              // two readers of one record disagreeing about the rule it encodes.\n              // No `force`/`--drop-embeddings` equivalent exists on this route,\n              // so the flag options go unset and `'discard'` is unreachable —\n              // it is folded into the abandon arm rather than given an invented\n              // flag. `maxAttempts` is left to the shared default.\n              const resume = priorCheckpoint\n                ? decideEmbeddingResume(priorCheckpoint, embeddingIdentity)\n                : undefined;\n              if (resume?.action === 'abort') throw new Error(resume.error);\n              if (resume?.action === 'abandon' || resume?.action === 'discard') {\n                logger.warn({ repo: entry.name }, resume.log);","sourceCodeStart":1751,"sourceCodeEnd":1787,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/server/api.ts#L1751-L1787","documentation":"POST /api/embed loads repository metadata from the resolved repo's storagePath (loadMeta); when it gets null the embedding pipeline cannot run, because embeddings are computed against an existing GitNexus index. The error tells you the storage directory has no metadata — the repo was never analyzed by this server (or its data is gone).","triggerScenarios":"POST /api/embed?repo=X where X is registered but its storagePath lacks the metadata file: embedding was requested before any analyze ran, the index/data was deleted, or GITNEXUS_HOME now points somewhere else than when the repo was indexed.","commonSituations":"Trying to embed immediately after registering a repo; a Docker container recreated with an empty /data/gitnexus volume (GITNEXUS_HOME) while the registry survived; moving/copying the data dir without metadata; pointing GITNEXUS_HOME at a fresh path so resolveRepo returns a stale entry.","solutions":["Run a full analysis first — POST /api/analyze (url or path) or `gitnexus analyze` on the machine — then retry /api/embed","Verify the repo's storagePath on disk actually contains the metadata/index files","Check GITNEXUS_HOME consistency between the process that indexed and the process serving /api/embed","If the volume was wiped, re-index and re-embed from scratch"],"exampleFix":"# before\ncurl -X POST http://localhost:4747/api/embed?repo=myrepo # 500: metadata missing\n\n# after\ncurl -X POST http://localhost:4747/api/analyze -H 'content-type: application/json' -d '{\"url\":\"https://github.com/user/myrepo.git\"}'\n# wait for job completion, then\ncurl -X POST http://localhost:4747/api/embed?repo=myrepo","handlingStrategy":"validation","validationCode":"// pre-flight: the repo must already have an index on this server\nasync function repoIsIndexed(repo, fetchEntry) {\n  const entry = await fetchEntry(repo); // registry/storage resolution\n  return Boolean(entry && entry.storagePath && entry.hasIndex);\n}","typeGuard":"function isAnalyzedRepoEntry(entry) {\n  return Boolean(entry && entry.storagePath && entry.indexedAt);\n}","tryCatchPattern":"try { await runEmbeddings(repo); }\ncatch (e) {\n  if (/Repository metadata is missing/.test(String(e.message))) {\n    await runFullAnalyze(repo); // establish the index first\n    return runEmbeddings(repo); // then retry once\n  }\n  throw e;\n}","preventionTips":["Always run analyze to completion before /api/embed on a repo","Keep GITNEXUS_HOME (and the Docker /data/gitnexus volume) stable between indexing and embedding","Monitor the repo list for entries whose storagePath no longer exists on disk"],"tags":["embeddings","http-api","missing-metadata","initialization-order"],"backgroundTag":"missing-metadata","analyzedSha":"0d1aed942f0e8b5d3bac27519fff441aceea722d","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}