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

  1. 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).
  2. Restart the dev server / redeploy after adding the var so the new value is loaded.
  3. Guard with getAiConfig(): skip AI work when !config.apiKeyConfigured and use rule-based output.
  4. 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

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


AI-assisted analysis of justjavac/wechat-miniapp-radar@02a010ecea (2026-08-12). Data as JSON: /api/errors/c3a598a422855279. Report an issue: GitHub.