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
- Run `gitnexus analyze --embeddings --force` to rebuild all embeddings under the current identity.
- Or restore the previous provider/model configuration so the run identity matches the checkpoint, then sync.
- Standardize embedding env vars across your team/CI so everyone resolves the same identity.
- 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
- Pin EMBEDDING_PROVIDER/MODEL/DIMS in committed config or CI env so every run resolves the same identity.
- When upgrading models, plan a full `analyze --embeddings --force` rebuild as part of the migration.
- Use separate storage paths for experimental embedding configurations.
- Record the embedding identity in your project README/runbook and check it before syncing.
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
- decision.error (embedding resume decision abort)
- No GitNexus index found for
- The LadybugDB graph store at
- The LadybugDB graph store at
- The structural index is incomplete. Run gitnexus analyze…
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 recordedView on GitHub (pinned to ac9a4e9abd)