abhigyanpatwari/GitNexus · error

Cannot sync embeddings: the index checkpoint was written by

Error message

Cannot sync embeddings: the index checkpoint was written by ${checkpoint.model} (${checkpoint.provider}) at ${checkpoint.dimensions} dimensions, but this run resolves ${identity.model} (${identity.provider}) at ${identity.dimensions}. Run `gitnexus analyze --embeddings --force` to rebuild under the new identity.

What it means

The stored checkpoint's embedding identity (model, provider, dimensions) differs from the identity resolved in this run. Syncing would mix vectors from two embedding spaces in one table, so the command refuses and asks for a forced rebuild under the new identity.

Solutions

  1. Run `gitnexus analyze --embeddings --force` to rebuild all embeddings under the current identity.
  2. Or restore the previous provider/model configuration so the run identity matches the checkpoint, then sync.
  3. Standardize embedding env vars across your team/CI so everyone resolves the same identity.
  4. If you only intended a config experiment, index it in a separate storage path (GITNEXUS_STORAGE_PATH).

Example fix

// before
EMBEDDING_MODEL=text-embedding-3-large  # index built with small
$ gitnexus embeddings-sync .   # identity mismatch
// after
$ EMBEDDING_MODEL=text-embedding-3-large gitnexus analyze --embeddings --force
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the configured identity matches what the index was built with before syncing:
const cfgIdentity = {
  provider: process.env.EMBEDDING_PROVIDER,
  model: process.env.EMBEDDING_MODEL,
  dimensions: Number(process.env.EMBEDDING_DIMS),
};
const meta = loadIndexMeta(repo);
const ck = meta?.embeddingCheckpoint;
if (ck && (ck.model !== cfgIdentity.model || ck.provider !== cfgIdentity.provider ||
           ck.dimensions !== cfgIdentity.dimensions)) {
  await run('gitnexus analyze --embeddings --force');
}

Try / catch

try {
  await gitnexus.embeddingsSync(repo);
} catch (err) {
  if (err.message.startsWith('Cannot sync embeddings: the index checkpoint was written by')) {
    await run('gitnexus analyze --embeddings --force');
    await gitnexus.embeddingsSync(repo);
  } else throw err;
}

Prevention

When it happens

Trigger: Changing EMBEDDING provider/model/dimension configuration (env vars or settings) after an index was partially embedded, then running embeddings sync against the old checkpoint.

Common situations: Upgrading the embedding model (e.g. 1536-dim to 1024-dim), switching from local to HTTP provider or vice versa, team members with different model defaults running against a shared index.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15). Data as JSON: /api/errors/3e172364b426a5c3. Report an issue: GitHub.

Appendix: source

Thrown at gitnexus/src/cli/embeddings-sync.ts:97

    if (meta.embeddingCheckpoint) {
      const checkpoint = meta.embeddingCheckpoint;
      const decision = decideEmbeddingResume(checkpoint, identity);
      if (decision.action === 'abort') throw new Error(decision.error);
      const identityDiffers =
        checkpoint.provider !== identity.provider ||
        checkpoint.model !== identity.model ||
        checkpoint.dimensions !== identity.dimensions;
      // `abandon` on a foreign identity drops the pending set only. Existing
      // rows stay; sync would then embed the holes under the new identity and
      // mix vector spaces. Fail closed — rebuild via analyze.
      //
      // Every kind is gated, `unverified-count` included. Exempting it looked
      // safe because that kind only records "the count could not be read", but
      // `decideEmbeddingResume` returns `abandon` for it BEFORE comparing
      // identity, so the exemption was the only thing standing between a
      // foreign identity and a silently mixed table.
      if (identityDiffers) {
        throw new Error(
          `Cannot sync embeddings: the index checkpoint was written by ${checkpoint.model} ` +
            `(${checkpoint.provider}) at ${checkpoint.dimensions} dimensions, but this run ` +
            `resolves ${identity.model} (${identity.provider}) at ${identity.dimensions}. ` +
            'Run `gitnexus analyze --embeddings --force` to rebuild under the new identity.',
        );
      }
      cliInfo(decision.log);
      if (decision.action === 'resume') {
        forceReembedNodeIds = decision.pendingNodeIds;
        resumedFrom = decision.resumedFrom;
      }
    }

    // The vector column is FLOAT[N] fixed when the index was built, and the
    // pipeline deletes each batch's stale rows immediately before inserting the
    // replacements — so a width change here deletes rows it cannot re-insert.
    // `analyze` forces a full rebuild on the same mismatch; only a rebuild can
    // retype the column, so this writer refuses instead. An absent recorded

View on GitHub (pinned to ac9a4e9abd)