Problem
The Retrieval‑Augmented Generation (RAG) service, deployed with Docker Compose, fails during inference with a dimension mismatch error. The query encoder produces vectors of a different size than the document encoder, causing the retrieval component to raise an exception and abort the request.
2026-10-31 14:12:07,842 ERROR rag_service.inference - RuntimeError: Expected embedding dimension 768 but got 1024
Traceback (most recent call last):
File "/app/rag_service/inference.py", line 112, in handle_query
query_vec = self.query_encoder.encode(query)
File "/app/encoders/query_encoder.py", line 45, in encode
return self.model.encode(text)
File "/usr/local/lib/python3.10/site-packages/transformers/pipelines.py", line 312, in __call__
embeddings = self.model(**inputs)[0]
RuntimeError: Expected embedding dimension 768 but got 1024
Impact:
- All incoming queries return HTTP 500.
- Monitoring alerts fire on “RAG retrieval failure”.
- No new documents can be indexed because the document encoder also emits 1024‑dimensional vectors.
Root Cause
The failure originates from an uncoordinated upgrade of the embedding model in the query_encoder container. The Docker image was rebuilt with sentence‑transformers/all‑MiniLM‑L6‑v2 (output dimension 384) while the document_encoder still uses the older sentence‑transformers/all‑mpnet‑base‑v2 (output dimension 768). The RAG retrieval layer is hard‑coded to expect matching dimensions (default 768). Because the two encoders now emit vectors of different sizes, the FAISS index construction fails, resulting in the observed RuntimeError.
Why it happened:
- The
docker-compose.ymlreferenced a floating tagsentence-transformers:latestfor the query encoder. - During a routine CI run,
latestresolved to a newer model version with a different hidden size. - No version pinning or validation step existed to guarantee dimensional parity between the two encoders.
Debug
Step‑by‑step investigation that reproduced the mismatch:
- Inspect container logs – the error above clearly shows the expected vs. actual dimensions.
- Check the model files inside each container:
# Inside query_encoder container
docker exec -it rag_query_encoder bash -c "python - <<'PY'
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('/models')
print('Query encoder dim:', model.get_sentence_embedding_dimension())
PY"
Query encoder dim: 384
# Inside document_encoder container
docker exec -it rag_doc_encoder bash -c "python - <<'PY'
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('/models')
print('Document encoder dim:', model.get_sentence_embedding_dimension())
PY"
Document encoder dim: 768
# docker-compose.yml (original)
services:
query_encoder:
image: myorg/rag-encoder:latest
environment:
- MODEL_NAME=sentence-transformers:latest # ← problematic
document_encoder:
image: myorg/rag-encoder:1.3.0
environment:
- MODEL_NAME=sentence-transformers/all-mpnet-base-v2
config.yaml) expects 768‑dimensional vectors:
retriever:
embedding_dim: 768
index_type: faiss
Solution
Align both encoders to the same model version and dimension, and add explicit version pinning.
Before (problematic) configuration
# docker-compose.yml
services:
query_encoder:
image: myorg/rag-encoder:latest
environment:
- MODEL_NAME=sentence-transformers:latest
document_encoder:
image: myorg/rag-encoder:1.3.0
environment:
- MODEL_NAME=sentence-transformers/all-mpnet-base-v2
After (fixed) configuration
# docker-compose.yml
services:
query_encoder:
image: myorg/rag-encoder:1.3.0
environment:
- MODEL_NAME=sentence-transformers/all-mpnet-base-v2 # pinned to 768‑dim model
document_encoder:
image: myorg/rag-encoder:1.3.0
environment:
- MODEL_NAME=sentence-transformers/all-mpnet-base-v2
Additional steps:
- Rebuild the encoder image with the correct model bundled (or let it download at startup).
- Update
config.yamlif a different dimension is desired, e.g., switching both to a 384‑dim model, but ensure the value matches the actual model. - Run
docker compose up --build -dto redeploy.
Verify
After redeployment, confirm that both encoders report the same dimension and that a sample query succeeds.
# Verify dimensions
docker exec rag_query_encoder python -c "
from sentence_transformers import SentenceTransformer
print('Query dim:', SentenceTransformer('/models').get_sentence_embedding_dimension())
"
Query dim: 768
docker exec rag_doc_encoder python -c "
from sentence_transformers import SentenceTransformer
print('Doc dim:', SentenceTransformer('/models').get_sentence_embedding_dimension())
"
Doc dim: 768
# Run a health‑check request
curl -s -X POST http://localhost:8080/rag/query -d '{"query":"What is the capital of France?"}' | jq .
{
"answer": "The capital of France is Paris."
}
Check logs for absence of the previous RuntimeError and confirm that the FAISS index loads without warnings.
Prevent
Implement safeguards to avoid future dimension mismatches:
| Guardrail | Implementation |
|---|---|
| Pin model versions in Docker images | Use immutable tags (e.g., sentence-transformers/all-mpnet-base-v2@sha256:…) instead of :latest. |
| Validate embedding dimension at container start‑up | Add a start‑up script that loads the model and exits with non‑zero status if model.get_sentence_embedding_dimension() differs from the value in config.yaml. |
| CI test matrix | Run an integration test that encodes a dummy query and a dummy document, asserts equal vector sizes, and fails the pipeline if they diverge. |
| Monitoring alert | Expose the embedding dimension as a Prometheus gauge (e.g., rag_encoder_embedding_dim{service="query"} 768) and alert on mismatched values. |
| Documentation lock | Record the approved model name and dimension in the repository’s README and enforce via code review checklists. |
Related Topic Hub: Distributed Systems Troubleshooting Hub
FAQ
- Why does the error only appear after a Docker image rebuild?
Because the rebuild pulled thelatesttag, which resolved to a newer model with a different hidden size. The document encoder image was not rebuilt, so the two containers diverged. - Can I use different models for query and document encoders?
Only if they share the exact same output dimension and are compatible with the retriever’s index type. Otherwise the retrieval layer cannot compute similarity scores. - How do I discover the embedding dimension of an arbitrary SentenceTransformer model?
Load the model in Python and callmodel.get_sentence_embedding_dimension(). This is the value that must match theembedding_dimfield in the RAG config. - Is there a way to make the RAG service auto‑adjust to dimension changes?
You could add a dynamic re‑initialization step that rebuilds the FAISS index with the new dimension, but this adds latency and complexity. Pinning versions is the simpler, more reliable approach. - What should I do if I must upgrade to a higher‑dimensional model?
Updateconfig.yamlto the newembedding_dim, rebuild both encoder containers with the same model, and re‑index all documents so the index matches the new vector size.