{"record":{"id":"9d2f7947d998675d","repo":"abhigyanpatwari/GitNexus","slug":"decision-error-embedding-resume-decision-abort","errorCode":null,"errorMessage":"decision.error (embedding resume decision abort)","messagePattern":"decision\\.error \\(embedding resume decision abort\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/cli/embeddings-sync.ts","lineNumber":82,"sourceCode":"    } catch {\n      throw new Error(\n        `The LadybugDB graph store at ${lbugPath} is missing. Run gitnexus analyze first.`,\n      );\n    }\n    if (!lbugStat.isFile()) {\n      throw new Error(\n        `The LadybugDB graph store at ${lbugPath} is not a usable database file. Run gitnexus analyze first.`,\n      );\n    }\n\n    const { resolveEmbeddingIdentity } = await import('../core/embeddings/embedding-identity.js');\n    const identity = resolveEmbeddingIdentity();\n    let forceReembedNodeIds: ReadonlySet<string> | undefined;\n    let resumedFrom: EmbeddingCheckpoint | undefined;\n    if (meta.embeddingCheckpoint) {\n      const checkpoint = meta.embeddingCheckpoint;\n      const decision = decideEmbeddingResume(checkpoint, identity);\n      if (decision.action === 'abort') throw new Error(decision.error);\n      const identityDiffers =\n        checkpoint.provider !== identity.provider ||\n        checkpoint.model !== identity.model ||\n        checkpoint.dimensions !== identity.dimensions;\n      // `abandon` on a foreign identity drops the pending set only. Existing\n      // rows stay; sync would then embed the holes under the new identity and\n      // mix vector spaces. Fail closed — rebuild via analyze.\n      //\n      // Every kind is gated, `unverified-count` included. Exempting it looked\n      // safe because that kind only records \"the count could not be read\", but\n      // `decideEmbeddingResume` returns `abandon` for it BEFORE comparing\n      // identity, so the exemption was the only thing standing between a\n      // foreign identity and a silently mixed table.\n      if (identityDiffers) {\n        throw new Error(\n          `Cannot sync embeddings: the index checkpoint was written by ${checkpoint.model} ` +\n            `(${checkpoint.provider}) at ${checkpoint.dimensions} dimensions, but this run ` +\n            `resolves ${identity.model} (${identity.provider}) at ${identity.dimensions}. ` +","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/cli/embeddings-sync.ts#L64-L100","documentation":"decideEmbeddingResume examined the stored embedding checkpoint against the current embedding identity and returned action 'abort'; the command throws with the decision's error message. This guards against resuming from a checkpoint that must not be reused (typically a foreign or unverified identity that cannot be safely migrated).","triggerScenarios":"meta.embeddingCheckpoint exists and decideEmbeddingResume classifies it as abort — e.g. the checkpoint kind is one that always aborts (such as unverified-count) or the stored checkpoint state is unusable for resume.","commonSituations":"Switching embedding providers/models mid-way; an interrupted run recorded a checkpoint kind that cannot be resumed; a count could not be verified during the previous run.","solutions":["Read decision.error in the thrown message for the specific abort reason and follow it.","Run `gitnexus analyze --embeddings --force` to discard the checkpoint and rebuild embeddings cleanly.","Restore the embedding provider/model environment (API keys, env vars) to what the checkpoint was written with if you want resume instead.","Remove/complete the interrupted run's checkpoint by re-running the interrupted command."],"exampleFix":"// before\n$ gitnexus embeddings-sync .   # abort per resume decision\n// after\n$ gitnexus analyze --embeddings --force\n$ gitnexus embeddings-sync .","handlingStrategy":"try-catch","validationCode":"// If you can read meta before syncing, refuse obvious abort cases yourself:\nconst meta = loadIndexMeta(repo);\nif (meta?.embeddingCheckpoint?.kind === 'unverified-count') {\n  await run('gitnexus analyze --embeddings --force'); // abort is the only safe path\n}","typeGuard":null,"tryCatchPattern":"try {\n  await gitnexus.embeddingsSync(repo);\n} catch (err) {\n  // decision.error aborts are not transient — a rebuild is the fix\n  await run('gitnexus analyze --embeddings --force');\n  await gitnexus.embeddingsSync(repo);\n}","preventionTips":["Let interrupted embedding runs complete or be explicitly rebuilt before starting new ones.","Keep provider/model config stable across runs of the same index.","Treat 'abort' resume decisions as rebuild-required, never retry the sync unchanged.","Monitor the previous run's completion status before launching sync."],"tags":["embeddings","checkpoint","resume","identity"],"backgroundTag":"invalid-state-transition","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-09-15T23:29:44.066Z","contentChangedAt":"2026-09-15T23:29:44.066Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}