Home / AI & GenAI / Vector Databases

AI & GenAIRunbookIntermediate

Sev1: vector search fails or returns nonsense after an embedding model change

Search throws dimension errors, or still works but returns irrelevant results, after someone changed the embedding deployment, model version or dimensions setting. Find which side changed, restore matching query and document embeddings, and lock the embedding config to the index.

Deepak Bhardwaj3 min read

Applies toRAG and semantic search on Azure AI Search, pgvector, Qdrant, OpenSearch, Pinecone; embeddings from Azure OpenAI, Bedrock, open models

Symptoms

Loud failure:

pgvector:     ERROR:  expected 1536 dimensions, not 3072
Azure AI Search: The vector field 'contentVector' ... dimensions mismatch
Qdrant:       Wrong input: Vector dimension error: expected dim: 1536, got 3072

Quiet failure (worse): no errors, but results are random-looking. The query and documents were embedded by different models with the same number of dimensions, so the vectors aren't comparable.

Step 1: what changed?

Check Where
Query embedding config App config: deployment/model ID, dimensions parameter
Ingestion embedding config Indexer skillset / pipeline config
Model deployment Azure: deployment's model name and version; Bedrock: model ID
Recent deploys App and pipeline release history

Quick test: embed a known document chunk now, and compare with its stored vector.

import numpy as np
stored = fetch_vector(doc_id="kb-123#4")
fresh  = embed(fetch_text(doc_id="kb-123#4"))
cos = np.dot(stored, fresh) / (np.linalg.norm(stored) * np.linalg.norm(fresh))
print(len(stored), len(fresh), round(cos, 4))

Same model and settings → cosine ≈ 1.0 (tiny differences are normal). Much lower → the models differ.

Step 2: restore service

Situation Fix
Query side changed, index unchanged Revert the query embedding config to the index's model
Ingestion changed, some documents re-embedded with new model Index is now mixed: roll back to the previous index version, or re-embed everything with one model
Deliberate model upgrade done halfway Point the app back to the old index until the new one is fully built and validated
Old model retired by provider Build a new index with the new model end to end; meanwhile use keyword-only search as a fallback

Keyword fallback for hybrid-capable stores (Azure AI Search): run the query with text only, no vector query, until vectors are consistent. It's worse than hybrid but much better than random results.

Step 3: rebuild properly (if needed)

  1. Create a new index/collection with the new dimensions.
  2. Re-embed all documents with the new model (batch, with rate limits).
  3. Validate with the labelled question set (recall@k).
  4. Switch the query embedding config and the index pointer together, in one config change.

See the embedding migration post for the full approach.

Step 4: lock config to the index

Store the embedding settings with the index, and have the app refuse to query with different ones:

INDEX_META = get_index_metadata("kb-v12")   # e.g. {"embedding_model": "text-embedding-3-large", "dimensions": 1024}

def embed_query(text):
    if (EMBED_CFG.model, EMBED_CFG.dimensions) != (INDEX_META["embedding_model"], INDEX_META["dimensions"]):
        raise RuntimeError("Embedding config does not match index metadata. Refusing to query.")
    return embed(text, model=EMBED_CFG.model, dimensions=EMBED_CFG.dimensions)

Failing loudly beats silently returning irrelevant results.

Warning

The dimensions parameter on models that support shortened embeddings changes the vectors. 1,024-dim and 3,072-dim embeddings from the same model are not interchangeable, and neither are versions of "the same" model from different providers.

Prevent it next time

  • Embedding model, version and dimensions are part of the index version, not separate app settings.
  • Startup check comparing query config with index metadata.
  • Pin embedding deployments' versions; track retirement dates.
  • Monitoring on average top-1 similarity score. A sudden drop is a strong signal of mismatch.