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.
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)
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 response JSON must be an object.
- AI provider rejected ${model}: ${providerError}
- AI provider returned an empty response for ${model}.
AI-assisted analysis of justjavac/wechat-miniapp-radar@02a010ecea (2026-08-12).
Data as JSON: /api/errors/c3a598a422855279.
Report an issue: GitHub.