justjavac/wechat-miniapp-radar · error · Error
OPENAI_API_KEY is not configured.
Error message
OPENAI_API_KEY is not configured.
What it means
Thrown by requestChatCompletion() in lib/ai-client.ts when process.env.OPENAI_API_KEY (trimmed) is empty at call time. It fires before any network call because the Authorization: Bearer header cannot be built without it. Important: the public createAiJsonCompletion() reads getAiConfig() and returns {ok:false,error:'AI is not configured.'} early when the key is absent, since in lib/ai-config.ts configured === apiKeyConfigured. Under a stable env this throw is therefore only reachable by calling the private requestChatCompletion() directly, or if the key is removed between the config snapshot and the request.
Solutions
- Set OPENAI_API_KEY in .env locally and in Vercel project env (use your OpenRouter key when OPENAI_API_URL is https://openrouter.ai/api/v1).
- Restart the dev server / redeploy after adding the var so the new value is loaded.
- Guard with getAiConfig(): skip AI work when !config.apiKeyConfigured and use rule-based output.
- Confirm via GET /api/health (reports AI integration status) or npm run integrations:verify.
Example fix
// before
const value = await requestChatCompletion({ config, model, messages, timeoutMs });
// after
import { getAiConfig } from "@/lib/ai-config";
if (!getAiConfig().apiKeyConfigured) {
return ruleBasedFallback();
} Defensive patterns
Strategy: validation
Validate before calling
import { getAiConfig } from "@/lib/ai-config";
const canCallAi = getAiConfig().apiKeyConfigured;
if (!canCallAi) {
// do not call requestChatCompletion expecting a value
} Prevention
- Treat createAiJsonCompletion as the only entry point; it already short-circuits on a missing key.
- For OpenRouter, put the OpenRouter key in OPENAI_API_KEY alongside OPENAI_API_URL=https://openrouter.ai/api/v1.
- After rotating the key, redeploy or restart so the new value is loaded.
When it happens
Trigger: Unit/integration tests calling requestChatCompletion() directly; a process where OPENAI_API_KEY was unset or cleared between getAiConfig() and the request; a harness that stubs getAiConfig() to report configured=true without exporting the key; OpenRouter users who set OPENAI_API_URL but forget the key.
Common situations: .env missing OPENAI_API_KEY (note: an OpenRouter key also goes in OPENAI_API_KEY, not a separate var); key set in one Vercel environment but the function runs in another; a value of only whitespace that trims to empty; CI secret not injected for the job.
Related errors
- DATABASE_URL is required for database operations.
- AI provider rejected
- AI provider returned an empty response for
- AI response JSON must be an object.
AI-assisted analysis of justjavac/wechat-miniapp-radar@02a010ecea (2026-08-12).
Data as JSON: /api/errors/c3a598a422855279.
Report an issue: GitHub.
Appendix: source
Thrown at lib/ai-client.ts:130
return JSON.parse(text) as ChatCompletionResponse;
} catch {
return null;
}
}
async function requestChatCompletion<T>({
config,
model,
messages,
timeoutMs
}: {
config: AiConfig;
model: string;
messages: AiPromptMessage[];
timeoutMs: number;
}) {
const apiKey = process.env.OPENAI_API_KEY?.trim();
if (!apiKey) throw new Error("OPENAI_API_KEY is not configured.");
const { response, text } = await fetchTextWithTimeout(
completionUrl(config),
{
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${apiKey}`,
...openRouterHeaders(config)
},
body: JSON.stringify({
model,
messages,
temperature: 0.2,
max_tokens: DEFAULT_AI_MAX_TOKENS,
stream: false,
...responseFormatForModel(config, model)
})View on GitHub (pinned to 02a010ecea)