abhigyanpatwari/GitNexus · error · HttpEmbeddingError
Embedding dimension mismatch: endpoint returned
Error message
Embedding dimension mismatch: endpoint returned ${vec.length}d vector, but expected ${expected}d. ${hint} What it means
HttpEmbeddingError thrown during httpEmbed() when the endpoint returns a vector whose width differs from the expected width (config.dimensions from GITNEXUS_EMBEDDING_DIMS, defaulting to 384). This is deliberately terminal on first occurrence, not retried (#2790): a width mismatch is an operator configuration error, not a transient endpoint fault, and retrying cannot change the vector width. The message embeds the actual width and an actionable hint.
Solutions
- Read the number in the message and set it explicitly: export GITNEXUS_EMBEDDING_DIMS=<returned-width> (the hint line already contains the exact assignment).
- If GITNEXUS_EMBEDDING_DIMS was explicitly set to the wrong value, update it to match the model's actual output width.
- After changing dims, re-run the full analyze/embedding pass so stored vectors match the new width; mixing widths corrupts similarity search.
- If the server should honor a dimensions request but does not, verify with curl that the dimensions field is accepted, and use GITNEXUS_EMBEDDING_REQUEST_DIMS only for what is sent on the wire.
Example fix
# before export GITNEXUS_EMBEDDING_MODEL=text-embedding-3-small # returns 1536d # GITNEXUS_EMBEDDING_DIMS unset -> expects default 384 gitnexus analyze # -> Embedding dimension mismatch: endpoint returned 1536d vector, but expected 384d. # after export GITNEXUS_EMBEDDING_DIMS=1536 gitnexus analyze # fresh index with 1536d vectors
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: embed one probe string and pin GITNEXUS_EMBEDDING_DIMS to the answer.
import { isHttpMode } from './core/embeddings/http-client.js';
export async function resolveEmbeddingDims(): Promise<number> {
if (!isHttpMode()) return 0; // local embedder path
const base = process.env.GITNEXUS_EMBEDDING_URL!.replace(/\/+$/, '');
const res = await fetch(`${base}/embeddings`, {
method: 'POST',
headers: {
'content-type': 'application/json',
authorization: `Bearer ${process.env.GITNEXUS_EMBEDDING_API_KEY ?? 'unused'}`,
},
body: JSON.stringify({ model: process.env.GITNEXUS_EMBEDDING_MODEL, input: ['ping'] }),
});
if (!res.ok) throw new Error(`dims probe failed: ${res.status}`);
const { data } = (await res.json()) as { data: { embedding: number[] }[] };
return data[0].embedding.length;
} Type guard
import { HttpEmbeddingError } from './core/embeddings/http-client.js';
export const isDimensionMismatchError = (e: unknown): e is HttpEmbeddingError =>
e instanceof HttpEmbeddingError && e.message.startsWith('Embedding dimension mismatch'); Try / catch
try {
vectors = await httpEmbed(texts);
} catch (err) {
if (isDimensionMismatchError(err)) {
// Terminal config error — do NOT retry; dims cannot change between calls.
const actual = /returned (\d+)d/.exec(err.message)?.[1];
throw new Error(
`Model width changed. Re-run with GITNEXUS_EMBEDDING_DIMS=${actual} and rebuild the index`,
{ cause: err },
);
}
throw err;
} Prevention
- Always set GITNEXUS_EMBEDDING_DIMS explicitly — never rely on the 384 default with hosted models.
- Run the one-string dims probe at pipeline start and fail if it disagrees with GITNEXUS_EMBEDDING_DIMS.
- Treat model changes as index-breaking: change model + dims together, then re-analyze from scratch.
- Keep a single source of truth (one .env) shared by indexing and search processes so both see identical dims.
When it happens
Trigger: Calling httpEmbed() after switching the embedding model (e.g. from a 384-dim MiniLM model to a 768-dim or 1536-dim model) without updating GITNEXUS_EMBEDDING_DIMS; or explicitly setting GITNEXUS_EMBEDDING_DIMS=384 while pointing at a model that outputs another width; or a server that ignores the requested dimensions parameter.
Common situations: Swapping a local Ollama model for an OpenAI text-embedding-3-* model (1536/3072 dims) while the index and env still assume 384; a gateway silently substituting a different model version; re-using an old .env against a new endpoint. Note the vector width is baked into the existing index, so changing dims requires re-embedding.
Related errors
- Embedding dimension mismatch: endpoint returned
- Embedding request failed
- GITNEXUS_EMBEDDING_DIMS must be a positive integer, got
- HTTP embedding not configured
- must be a non-negative integer, got
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-08-20).
Data as JSON: /api/errors/44f112d66ff16e38.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/core/embeddings/http-client.ts:674
// into the FLOAT[N] column which would cause a cryptic Kuzu error.
//
// Unlike the cardinality check this one stays *outside* the retry loop,
// deliberately. The expected width is `config.dimensions ?? DEFAULT_DIMS`
// (GITNEXUS_EMBEDDING_DIMS), which is NOT the `dimensions` value
// `httpEmbedBatch` receives — that is `config.requestDimensions`, which
// `GITNEXUS_EMBEDDING_REQUEST_DIMS` can set to a different number or to
// `undefined` (`omit`). More importantly a width mismatch is an operator
// *configuration* error, not an endpoint fault: retrying it three times
// can never change the answer, and routing it through the retry loop
// would count a healthy endpoint's responses toward the shared circuit
// breaker. The message is an actionable config hint, so it is terminal
// on the first attempt by design (#2790).
const expected = config.dimensions ?? DEFAULT_DIMS;
if (vec.length !== expected) {
const hint = config.dimensions
? 'Update GITNEXUS_EMBEDDING_DIMS to match your model output.'
: `Set GITNEXUS_EMBEDDING_DIMS=${vec.length} to match your model output.`;
throw new HttpEmbeddingError(
`Embedding dimension mismatch: endpoint returned ${vec.length}d vector, ` +
`but expected ${expected}d. ${hint}`,
);
}
allVectors.push(vec);
}
}
return allVectors;
};
/**
* Embed a single query text via the HTTP backend.
* Convenience for MCP search where only one vector is needed.
*
* @param text - Query text to embed
* @returns Embedding vector as number arrayView on GitHub (pinned to ac9a4e9abd)