LangChain OpenAI API Error? Fix AuthenticationError, ChatOpenAI & Model Names
Troubleshoot LangChain + OpenAI errors — AuthenticationError even with a correct key, wrong class (ChatOpenAI vs OpenAI), deprecated model names, chain.invoke() vs chain.run(), structured output failures, and LangSmith tracing slowdowns.
Common errors and fixes
1. AuthenticationError — correct key but still failing
The error looks like this:
openai.AuthenticationError: Error code: 401 - {'error': {'message': 'Incorrect API key provided'}} The two most common causes: the environment variable is named wrong, or it is set after the import. The fix:
import os
# ✅ Set BEFORE importing ChatOpenAI — must be OPENAI_API_KEY exactly
os.environ["OPENAI_API_KEY"] = "sk-..."
from langchain_openai import ChatOpenAI
# ✅ Or pass directly to the constructor (also reads env var as fallback)
llm = ChatOpenAI(model="gpt-4o", api_key="sk-...")
# ❌ Wrong variable names that look right but don't work:
# os.environ["OPENAI_KEY"] = "sk-..." # missing _API_
# os.environ["openai_api_key"] = "sk-..." # must be uppercase - Verify the key in the OpenAI dashboard — if it starts with
sk-proj-it is a project key and requires the project to have API access enabled. - In
.envfiles, load withpython-dotenvbefore any imports:from dotenv import load_dotenv; load_dotenv(). - Shell:
export OPENAI_API_KEY=sk-...(Linux/macOS) or$env:OPENAI_API_KEY="sk-..."(PowerShell).
2. ChatOpenAI vs OpenAI — wrong class for chat models
Using the OpenAI class with a chat model name causes an InvalidRequestError because it calls the completions endpoint instead of chat/completions:
from langchain_openai import ChatOpenAI, OpenAI
# ❌ OpenAI class — only for legacy text-completion models (deprecated)
llm = OpenAI(model="gpt-4o") # InvalidRequestError
# ✅ ChatOpenAI — for ALL current OpenAI chat models
llm = ChatOpenAI(model="gpt-4o") # recommended, best price/performance
llm = ChatOpenAI(model="gpt-4-turbo") # if you need a specific turbo version
llm = ChatOpenAI(model="gpt-3.5-turbo") # cheaper, faster
# ✅ With extra params
llm = ChatOpenAI(
model="gpt-4o",
temperature=0.7,
max_tokens=512,
streaming=True, # enables token streaming
) - Rule of thumb: if the model name contains "gpt-3.5-turbo", "gpt-4", "gpt-4o", or "o1" — use
ChatOpenAI. - Old import path
from langchain.chat_models import ChatOpenAIis removed in v0.2 — usefrom langchain_openai import ChatOpenAI.
3. Model name errors — deprecated or misspelled names
OpenAI returns 404 model_not_found for deprecated snapshot names:
# ❌ Deprecated / snapshot names — will 404
ChatOpenAI(model="gpt-4-0314") # retired snapshot
ChatOpenAI(model="gpt-4-32k") # no longer available
ChatOpenAI(model="gpt-3.5-turbo-0301")
# ✅ Current aliases (as of 2025) — prefer these
ChatOpenAI(model="gpt-4o") # points to latest gpt-4o
ChatOpenAI(model="gpt-4o-mini") # cheaper, fast
ChatOpenAI(model="gpt-4-turbo") # latest gpt-4-turbo
ChatOpenAI(model="gpt-3.5-turbo") # legacy but still active
ChatOpenAI(model="o1") # reasoning model
ChatOpenAI(model="o1-mini") # cheaper reasoning Check platform.openai.com/docs/models for the current list — model availability depends on your account tier.
4. chain.run() removed in v0.2 — use chain.invoke()
LangChain v0.2 removed .run() and .__call__() from LCEL chains. The error is AttributeError: 'RunnableSequence' object has no attribute 'run':
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI(model="gpt-4o")
prompt = ChatPromptTemplate.from_template("Summarise: {text}")
chain = prompt | llm | StrOutputParser()
# ❌ v0.1 style — removed in v0.2
result = chain.run("My text here") # AttributeError
result = chain({"text": "My text here"}) # AttributeError
# ✅ v0.2+ style
result = chain.invoke({"text": "My text here"}) # sync
result = await chain.ainvoke({"text": "My text here"}) # async
for chunk in chain.stream({"text": "My text here"}): # streaming
print(chunk, end="", flush=True) - Legacy LLMChain: if you used
LLMChain(llm=..., prompt=...), its.run()still works in v0.2 but is deprecated — it emits a warning and will be removed. Migrate to LCEL. - invoke() input: pass a dict matching your prompt's input variables. A single-variable prompt can also accept a plain string:
chain.invoke("hello").
5. "Cannot read properties of undefined" — accessing .content on wrong object
When you call llm.invoke() directly (without a parser), it returns an AIMessage object, not a string:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI(model="gpt-4o")
# llm.invoke() returns AIMessage, not str
response = llm.invoke("Tell me a joke")
print(response) # AIMessage(content='Why did the...', ...)
print(response.content) # ✅ the text string
# With a prompt list
response = llm.invoke([HumanMessage(content="Tell me a joke")])
print(response.content) # ✅
# Add StrOutputParser to get a plain string from the chain
from langchain_core.output_parsers import StrOutputParser
chain = llm | StrOutputParser()
text = chain.invoke("Tell me a joke")
print(text) # ✅ plain str - Structured output: use
llm.with_structured_output(MyPydanticModel)— this returns a Pydantic object, notAIMessage. Do not call.contenton its result. - JavaScript/TypeScript:
@langchain/openaireturns the sameAIMessagestructure — accessresponse.contentas a string.
6. Version pinning — langchain vs @langchain/openai (JS/TS)
In Python, langchain and langchain-openai must be from the same release generation. In JS/TS, langchain and @langchain/openai are separate packages with independent versioning:
# Python — check all versions together
pip show langchain langchain-core langchain-openai
# Upgrade everything at once to avoid mismatches
pip install --upgrade langchain langchain-core langchain-openai
# TS/JS — install separately
npm install langchain @langchain/openai @langchain/core
# TS usage
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
const llm = new ChatOpenAI({ model: "gpt-4o", temperature: 0 });
const prompt = ChatPromptTemplate.fromTemplate("Answer: {question}");
const chain = prompt.pipe(llm).pipe(new StringOutputParser());
const result = await chain.invoke({ question: "What is 2+2?" }); - Python:
langchain[openai]extras syntax is deprecated — installlangchain-openaidirectly. - JS/TS peer dep errors: pin
@langchain/coreto the version that bothlangchainand@langchain/openaiagree on; check withnpm ls @langchain/core.
7. LangSmith tracing causing slowdowns
If each chain call takes 2–5 seconds longer than expected, LangSmith tracing is likely adding blocking network calls. Disable or configure it:
# Disable tracing entirely
import os
os.environ["LANGCHAIN_TRACING_V2"] = "false"
# Or unset if you don't need it in production
# del os.environ["LANGCHAIN_TRACING_V2"]
# Enable tracing correctly (all 3 vars required)
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "ls__..." # from smith.langchain.com
os.environ["LANGCHAIN_PROJECT"] = "my-project" # optional project name
# Suppress tracing for a single call without changing env vars
result = chain.invoke({"input": "hello"}, config={"callbacks": []}) - Check LangSmith status on Prismix — if LangSmith is degraded, tracing blocks every call until timeout.
- Background tracing: set
LANGCHAIN_TRACING_BACKGROUND=trueto make tracing non-blocking (experimental in some versions).
Get an email the next time OpenAI goes down
Outage alerts for OpenAI, straight to your inbox. No account needed, unsubscribe in every email.
Watching more than one service? A free account covers 5 services + a daily digest — and Pro is currently free.
FAQ
Why does LangChain throw AuthenticationError even with the correct OpenAI key?
The most common cause is the environment variable name. It must be exactly OPENAI_API_KEY (uppercase, with _API_). Also, set it before importing ChatOpenAI — the module reads the env var at import time in some versions. If using a .env file, call load_dotenv() before any LangChain imports.
Should I use ChatOpenAI or OpenAI in LangChain?
Use ChatOpenAI for all current OpenAI models (gpt-4o, gpt-4-turbo, gpt-3.5-turbo, o1). The OpenAI class targets the legacy text-completions endpoint (text-davinci-003 etc.) which OpenAI has deprecated. Passing a chat model name to OpenAI() returns an InvalidRequestError.
Which model name should I use — gpt-4, gpt-4o, or gpt-4-turbo?
Use gpt-4o for the best price–performance ratio as of 2025. gpt-4 points to the original GPT-4 (slower, expensive). gpt-4-turbo is the stabilised turbo alias. Snapshot names like gpt-4-0314 are retired and return 404 model_not_found.
Why does LangSmith tracing make my chain slow?
LangSmith tracing is synchronous by default and adds a blocking network call per chain run. Set LANGCHAIN_TRACING_V2=false to disable it, or pass config={"callbacks": []} to suppress tracing for one call. If LangSmith itself is down, every traced call will block until the HTTP timeout.