How to Fix 'authentication failed in production' in CrewAI (TypeScript)
When CrewAI throws authentication failed in production, it usually means your agent or tool is trying to call an LLM provider with credentials that work locally but are missing, malformed, or unavailable in the deployed environment. In TypeScript projects, this most often shows up after a deploy to Vercel, Docker, ECS, or a Node runtime where .env loading behaves differently than on your laptop.
The key point: this is almost never a CrewAI bug. It’s usually a configuration mismatch between your local setup and production runtime.
The Most Common Cause
The #1 cause is that your API key is loaded from .env locally, but never reaches the production process. In TypeScript apps, people often rely on dotenv.config() in a file that doesn’t run in production, or they reference process.env too early.
Here’s the broken pattern:
// broken.ts
import { Agent } from "crewai";
import dotenv from "dotenv";
dotenv.config();
const agent = new Agent({
role: "Support Analyst",
goal: "Answer customer questions",
backstory: "You handle banking support tickets.",
llm: {
provider: "openai",
apiKey: process.env.OPENAI_API_KEY,
model: "gpt-4o-mini",
},
});
And here’s the fixed pattern:
// fixed.ts
import { Agent } from "crewai";
const apiKey = process.env.OPENAI_API_KEY;
if (!apiKey) {
throw new Error("Missing OPENAI_API_KEY in runtime environment");
}
const agent = new Agent({
role: "Support Analyst",
goal: "Answer customer questions",
backstory: "You handle banking support tickets.",
llm: {
provider: "openai",
apiKey,
model: "gpt-4o-mini",
},
});
| Broken | Fixed |
|---|---|
Relies on dotenv.config() inside app code | Reads env vars directly from the runtime |
Fails when .env is not shipped to prod | Fails fast if OPENAI_API_KEY is missing |
| Hides config problems until runtime call | Surfaces config issues at startup |
If you’re using CrewAI through a wrapper like Crew, Agent, or a custom LLM adapter, the same rule applies: credentials must exist in the actual deployment environment, not just your repo.
Other Possible Causes
1) Wrong environment variable name
This happens when local and production use different names.
// wrong
process.env.OPENAI_KEY
// right
process.env.OPENAI_API_KEY
If you’re using Azure OpenAI or another provider, check the exact variable name expected by your integration. A typo here can still produce a generic authentication failure downstream.
2) Provider mismatch
You may be sending an OpenAI key to an Anthropic client, or vice versa.
// wrong
new Agent({
llm: {
provider: "anthropic",
apiKey: process.env.OPENAI_API_KEY,
model: "gpt-4o-mini",
},
});
// right
new Agent({
llm: {
provider: "openai",
apiKey: process.env.OPENAI_API_KEY,
model: "gpt-4o-mini",
},
});
CrewAI will often surface this as an auth error because the upstream SDK rejects the request before any task runs.
3) Secret exists locally but not in production
This is common on Vercel, Netlify, Docker Compose, and CI/CD pipelines.
# docker-compose.yml
services:
app:
build: .
environment:
NODE_ENV: production
# OPENAI_API_KEY missing here
Fix it by injecting the secret explicitly:
services:
app:
build: .
environment:
NODE_ENV: production
OPENAI_API_KEY: ${OPENAI_API_KEY}
In hosted platforms, verify the secret is set in the right project, branch, and environment scope.
4) Key format includes quotes or whitespace
A copied secret can contain hidden spaces or newline characters.
const apiKey = process.env.OPENAI_API_KEY?.trim();
That small .trim() matters more than people think. If your secret manager exported "sk-abc123" with quotes included as part of the value, authentication can fail even though the variable looks correct at first glance.
How to Debug It
- •Log whether the variable exists at startup
- •Don’t print the full key.
- •Print only presence and length.
const key = process.env.OPENAI_API_KEY;
console.log("OPENAI_API_KEY present:", Boolean(key), "length:", key?.length ?? 0);
- •
Verify the exact runtime where it fails
- •Local Node.js?
- •Docker container?
- •Serverless function?
- •Worker thread?
A lot of “works locally” cases are just
.envfiles not being loaded in prod. - •
Check which provider CrewAI is actually calling
- •Inspect your
Agentconfig. - •Confirm
provider,model, and credential fields match. - •If you use wrappers around CrewAI classes like
Agent,Task, orCrew, trace where env vars are read.
- •Inspect your
- •
Run a minimal auth test outside CrewAI
- •Call the provider SDK directly with the same key.
- •If that fails too, it’s not CrewAI.
- •If that passes, inspect how your CrewAI wrapper passes credentials into the LLM client.
Prevention
- •Fail fast at startup if required secrets are missing.
- •Keep all production secrets in your deployment platform’s secret store, not in
.envfiles committed to memory and forgotten. - •Normalize credential access through one config module so every
Agentand tool reads from the same validated source.
If you want one rule to keep this out of prod incidents, use this:
never let a CrewAI agent construct its own auth state implicitly.
Make credentials explicit, validate them once, and wire them into every Agent consistently. That removes most of the “authentication failed in production” cases before they ship.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
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