Improving Error Messages for Non-OpenAI Embedding Providers in LangChain
When OpenAIEmbeddings is used with third-party providers, cryptic errors replace helpful guidance. The fix: better error messages and documentation.
The Problem
OpenAIEmbeddings in LangChain is commonly used with non-OpenAI providers (OpenRouter, Ollama, vLLM) by simply changing the base_url. But when users did this, they often hit a cryptic error:
ValueError: No embedding data receivedNo context, no guidance on what went wrong.
Root Cause Analysis
I investigated why non-OpenAI providers fail and identified two separate causes:
Cause 1: Token arrays as input. By default, OpenAIEmbeddings tokenizes text using tiktoken and sends token arrays (list[int]) to the API. OpenAI's API accepts this, but most third-party providers expect raw text strings and reject or silently return empty results for token arrays.
The relevant code path:
# Default path: tokenize first, then send token IDs
tokens = self._tokenize(texts, chunk_size)
response = self.client.create(input=tokens, ...) # tokens is list[list[int]]Cause 2: Base64 encoding. The openai SDK automatically sets encoding_format="base64" for efficiency. OpenAI's API supports this, but third-party providers often don't — they return an empty response or an error.
The Fix
Rather than changing the default behavior (which could break existing OpenAI users), I enhanced the error message to guide users to the correct configuration:
The fix also improved the documentation. I added an "OpenAI-compatible APIs" section to the class docstring with a working example:
from langchain_openai import OpenAIEmbeddings
# For non-OpenAI providers: bypass tokenization and base64 encoding
embeddings = OpenAIEmbeddings(
model="...",
base_url="...",
check_embedding_ctx_length=False, # Send raw text, not tokens
)I also updated the docstrings for check_embedding_ctx_length and tiktoken_enabled to explicitly mention non-OpenAI use cases.
Why Not Auto-Detect?
I considered automatically detecting non-OpenAI URLs and switching behavior, but rejected it because:
- There's no reliable heuristic — some providers clone OpenAI's exact behavior including token input
- Silently changing behavior based on URL is surprising and hard to debug
- A clear error message with actionable guidance is more transparent
Key Takeaways
- Good error messages are a feature. The original "No embedding data received" told users nothing about what to do. The improved error message tells users exactly which settings to change and why.
- Documentation is part of the fix. Updating docstrings and adding usage examples prevents future users from hitting the same issue.
- Don't over-automate. Sometimes the best fix is telling the user what to do, not silently doing it for them.
Impact & Reflection
Impact: OpenAIEmbeddings is one of the most commonly used classes in the LangChain ecosystem. As more teams adopt open-source models via Ollama, vLLM, and other OpenAI-compatible APIs, this error message improvement prevents a confusing onboarding experience. Instead of debugging a cryptic "No embedding data received" error, users now get actionable guidance pointing them to the exact parameters to change.
What I learned about developer experience as engineering: This was the "smallest" PR in terms of code changes, but it might help the most people. It reframed my understanding of what "impactful engineering" means: sometimes the highest-leverage fix isn't a clever algorithm or a deep bug hunt — it's a clear error message that saves thousands of developers 30 minutes of debugging each. Developer experience is engineering, not just polish.
Why I rejected the auto-detection approach: I seriously considered auto-detecting non-OpenAI URLs and switching behavior automatically. The implementation would have been straightforward. But after thinking about it from the user's perspective, I realized that silent behavior changes based on URL patterns are exactly the kind of "magic" that causes hard-to-debug issues later. Being explicit (clear error message + documentation) is almost always better than being clever (auto-detection). This principle — prefer explicit over magic — now guides all my API design decisions.