How to Fix 'invalid API key in production' in LangChain (Python)

By Cyprian AaronsUpdated 2026-04-21
invalid-api-key-in-productionlangchainpython

When LangChain says invalid API key in production, it usually means your app is not sending the key you think it is. In practice, this shows up after deployment when local .env loading works, but the production runtime has a missing, stale, malformed, or wrong-provider key.

The error often appears when instantiating ChatOpenAI, OpenAIEmbeddings, or any other LangChain wrapper that calls an external LLM API. The key point: LangChain is rarely the problem; your environment wiring is.

The Most Common Cause

The #1 cause is loading environment variables locally with load_dotenv() and assuming production will have the same setup.

In development, this works because .env exists on disk. In production, your container, serverless runtime, or process manager may not load that file at all.

Broken vs fixed pattern

Broken patternFixed pattern
Relies on .env at runtimeUses real environment variables from the deployment platform
Instantiates clients before env is loadedLoads config before creating LangChain objects
Fails silently until first requestFails fast if the key is missing
# broken.py
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o-mini")  # reads env too early

load_dotenv()  # too late for already-created objects

response = llm.invoke("Hello")
print(response.content)
# fixed.py
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI

load_dotenv()  # local dev only; production should inject env vars

api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
    raise RuntimeError("OPENAI_API_KEY is missing")

llm = ChatOpenAI(
    model="gpt-4o-mini",
    api_key=api_key,
)

response = llm.invoke("Hello")
print(response.content)

If you are using ChatOpenAI, the failure in logs often looks like one of these:

  • openai.AuthenticationError: Error code: 401 - {'error': {'message': 'Incorrect API key provided'}}
  • openai.AuthenticationError: Invalid authentication credentials
  • langchain_core.exceptions.OutputParserException later in the chain if the model call failed upstream

The fix is to make sure the production process gets the real key before Python starts handling requests.

Other Possible Causes

1. Wrong environment variable name

LangChain wrappers look for provider-specific variables. For OpenAI, use OPENAI_API_KEY, not API_KEY or LANGCHAIN_API_KEY.

# broken
os.environ["API_KEY"] = "sk-..."
llm = ChatOpenAI(model="gpt-4o-mini")
# fixed
os.environ["OPENAI_API_KEY"] = "sk-..."
llm = ChatOpenAI(model="gpt-4o-mini")

2. Key injected into the wrong process

This happens a lot with Gunicorn, Uvicorn, Docker, and systemd. The shell where you tested has the variable, but the running service does not.

# broken: set in your shell only
export OPENAI_API_KEY=sk-...
gunicorn app:app   # maybe not inheriting what you expect in prod
# fixed: set in deployment config or container env
docker run -e OPENAI_API_KEY=sk-... my-app

For Kubernetes:

env:
  - name: OPENAI_API_KEY
    valueFrom:
      secretKeyRef:
        name: openai-secret
        key: api_key

3. Using a revoked or rotated key

A valid-looking string can still fail if it was rotated in the provider dashboard.

llm = ChatOpenAI(
    model="gpt-4o-mini",
    api_key="sk-oldrevokedkey123"
)

Fix by verifying the active secret in your vault or secret manager and redeploying after rotation.

4. Mixing providers and keys

This happens when you use an Anthropic or Azure OpenAI endpoint with an OpenAI key, or vice versa. LangChain classes are provider-specific.

# broken: OpenAI key with Azure client settings mismatch
from langchain_openai import AzureChatOpenAI

llm = AzureChatOpenAI(
    azure_deployment="my-deployment",
    api_key=os.getenv("OPENAI_API_KEY"),  # wrong source in many setups
    azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
)
# fixed: use the correct provider secret and config
llm = AzureChatOpenAI(
    azure_deployment="my-deployment",
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),
    azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
    api_version="2024-02-15-preview",
)

How to Debug It

  1. Print exactly what your process sees Check whether the variable exists at runtime, not just in your terminal.

    import os
    print(repr(os.getenv("OPENAI_API_KEY")))
    
  2. Verify object creation order Make sure you load env vars before creating ChatOpenAI, AzureChatOpenAI, or embeddings classes. If initialization happens at module import time, move it behind app startup code.

  3. Test outside LangChain Call the provider SDK directly with the same key. If raw SDK auth fails, LangChain is innocent.

    from openai import OpenAI
    
    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
    print(client.models.list())
    
  4. Check deployment secrets and logs Compare local .env, CI secrets, container env vars, and cloud secret manager values. Look for:

    • trailing spaces in secrets
    • old rotated keys still mounted in pods
    • wrong secret name in Helm/Terraform/serverless config

Prevention

  • Load configuration from environment variables injected by your platform, not from .env files in production.
  • Fail fast on startup if required secrets are missing.
  • Keep provider keys isolated by service:
    • OPENAI_API_KEY
    • ANTHROPIC_API_KEY
    • AZURE_OPENAI_API_KEY

If you want to avoid this class of issue entirely, treat API keys as deployment-time inputs and validate them before constructing any LangChain client. That gives you a clean startup failure instead of a noisy runtime incident.


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