How to Fix 'embedding dimension mismatch in production' in LangGraph (Python)

By Cyprian AaronsUpdated 2026-04-22
embedding-dimension-mismatch-in-productionlanggraphpython

What the error means

embedding dimension mismatch in production usually means your vector store was created with one embedding model, but your LangGraph app is now trying to write or query with a different one. In practice, this shows up after a model swap, a deployment rollback, or when one service uses text-embedding-3-small and another still uses text-embedding-ada-002.

The failure often comes from lower-level vector DB errors surfaced through LangGraph nodes, for example:

  • ValueError: expected embedding dimension 1536, got 3072
  • PineconeException: Vector dimension 1536 does not match the dimension of the index 3072
  • QdrantClientException: Wrong vector size
  • chromadb.errors.InvalidDimensionException: Embedding dimension mismatch

The Most Common Cause

The #1 cause is mixing embedding models across environments or graph nodes.

You create the index with one embedding size, then later your LangGraph node uses a different embedding class. The graph code looks fine, but the vector store rejects the insert or similarity search because the stored collection schema is fixed.

Broken vs fixed pattern

Broken patternFixed pattern
Index created with text-embedding-ada-002 and later queried with text-embedding-3-largeUse one embedding config everywhere, or migrate/rebuild the index
Different nodes instantiate different embedding classesCentralize embeddings in one factory/module
# broken.py
from langchain_openai import OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore

# Index was created earlier with 1536 dims
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")  # 3072 dims

vectorstore = PineconeVectorStore.from_existing_index(
    index_name="support-docs",
    embedding=embeddings,
)

# Somewhere inside a LangGraph node
docs = vectorstore.similarity_search("refund policy", k=3)
# fixed.py
from langchain_openai import OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore

# Keep the same model that was used to build the index
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")  # 1536 dims

vectorstore = PineconeVectorStore.from_existing_index(
    index_name="support-docs",
    embedding=embeddings,
)

docs = vectorstore.similarity_search("refund policy", k=3)

If you want to change models, do not reuse the old collection blindly. Rebuild the index with the new dimension or create a new namespace/index and migrate data.

Other Possible Causes

1) You changed providers but kept the same index

OpenAI, Cohere, Voyage, and local sentence-transformers models all produce different dimensions. A common production mistake is swapping providers in config without recreating the vector DB schema.

# config changed from OpenAI to local model
EMBEDDING_MODEL = "all-MiniLM-L6-v2"  # usually 384 dims

# but your Pinecone index was created at 1536 dims

2) One LangGraph node uses a different embedding instance

This happens when each node imports its own dependencies and builds its own retriever.

# node_a.py
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

# node_b.py
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")

In LangGraph, that becomes painful because state can flow through multiple nodes and only one of them needs to hit the wrong retriever to fail.

3) Your persisted collection survived an old schema

Chroma, Qdrant, Weaviate, and similar stores keep collection metadata. If you restart production with a new model but reuse the same persistent path or collection name, you can hit dimension errors even though your code is correct.

# same collection name reused after model change
vectorstore = Chroma(
    collection_name="claims_kb",
    persist_directory="/data/chroma",
    embedding_function=embeddings,
)

Fix by deleting/recreating the collection or versioning it:

collection_name = "claims_kb_v2"

4) You are mixing raw vectors from multiple services

If one LangGraph node writes embeddings directly and another uses a framework wrapper, it is easy to push incompatible vectors into the same store.

# bad: manual vector from another service
vector = [0.12] * 768   # wrong size for your index
index.upsert([("doc_1", vector)])

Keep all writes behind one embedding adapter so every vector has identical dimensionality.

How to Debug It

  1. Check the exact exception and where it fires

    • If it fails on insert, your write path is wrong.
    • If it fails on retrieval, your query embeddings do not match the index.
    • Look for messages like:
      • expected dimension X
      • got Y
      • wrong vector size
  2. Print the embedding model name and dimension in every node

    print(embeddings.model)
    print(len(embeddings.embed_query("test")))
    

    If two nodes print different lengths, you found the mismatch.

  3. Inspect your vector DB schema

    • Pinecone: check index dimension in console or API.
    • Chroma/Qdrant/Weaviate: check collection metadata.
    • Confirm it matches your current embedding output length exactly.
  4. Trace LangGraph state to see which node touches vectors Add logging around every retriever/tool node:

    def retrieve(state):
        print("node=retrieve")
        return {"docs": retriever.invoke(state["query"])}
    

    The first node that hits storage is usually where mismatch appears.

Prevention

  • Centralize embeddings in one module and inject them into every LangGraph node.
  • Version indexes/collections whenever you change embedding models.
  • Add a startup check that compares:
    • configured model name
    • sample embedding length
    • target vector DB dimension

A simple guard saves production incidents:

expected_dim = 1536
actual_dim = len(embeddings.embed_query("dimension check"))

if actual_dim != expected_dim:
    raise RuntimeError(
        f"Embedding dimension mismatch: expected {expected_dim}, got {actual_dim}"
    )

If you are using LangGraph in production, treat embedding dimensions like database schema. Once they drift, retrieval breaks hard.


Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides