justjavac/wechat-miniapp-radar · error · Error
AI provider rejected ${model}: ${providerError}
Error message
AI provider rejected ${model}: ${providerError} What it means
Thrown by requestChatCompletion() in lib/ai-client.ts when the provider returns a non-2xx HTTP status. It first parses the error body via parseCompletionPayload() and stringifyProviderError() (which reads message/code and metadata.reason/raw/provider_name) and formats `AI provider rejected <model>: <detail>`; if no detail is parseable it falls back to `... with HTTP <status>`. The model name interpolated is the one actually requested (primary or fallback). createAiJsonCompletion() catches this, records the message, and tries the next model before returning ok:false.
Source
Thrown at lib/ai-client.ts:156
authorization: `Bearer ${apiKey}`,
...openRouterHeaders(config)
},
body: JSON.stringify({
model,
messages,
temperature: 0.2,
max_tokens: DEFAULT_AI_MAX_TOKENS,
stream: false,
...responseFormatForModel(config, model)
})
},
timeoutMs
);
const payload = parseCompletionPayload(text);
if (!response.ok) {
const providerError = stringifyProviderError(payload?.error);
throw new Error(providerError ? `AI provider rejected ${model}: ${providerError}` : `AI provider rejected ${model} with HTTP ${response.status}.`);
}
const content = payload?.choices?.[0]?.message?.content;
if (typeof content !== "string" || content.trim().length === 0) {
throw new Error(`AI provider returned an empty response for ${model}.`);
}
return parseJsonObject<T>(content);
}
export async function createAiJsonCompletion<T>({
messages,
timeoutMs = DEFAULT_AI_TIMEOUT_MS,
totalTimeoutMs = DEFAULT_AI_TOTAL_TIMEOUT_MS
}: {
messages: AiPromptMessage[];
timeoutMs?: number;
totalTimeoutMs?: number;View on GitHub (pinned to 02a010ecea)
Solutions
- Decode the interpolated detail first: 401/403 fix OPENAI_API_KEY; 402 add credits or switch model; 404 correct OPENAI_MODEL; 429 back off or raise quota; 400 response_format remove the model or add it to OPENROUTER_JSON_RESPONSE_FORMAT_MODELS.
- Let createAiJsonCompletion() try config.fallbackModel automatically; ensure OPENAI_FALLBACK_MODEL is a different, currently available model.
- For 429/5xx, retry with bounded exponential backoff at the caller.
- If all models fail, fall back to the app's rule-based advisor/scoring.
Example fix
// before
const result = await createAiJsonCompletion<T>({ messages });
// result.error may be 'AI provider rejected openai/gpt-oss-20b:free: ...'
// after
if (!result.ok) {
console.warn(result.error);
return ruleBasedFallback();
} Defensive patterns
Strategy: fallback
Try / catch
const result = await createAiJsonCompletion<T>({ messages });
if (!result.ok || !result.value) {
// result.error lists per-model rejection reasons joined by ' | '
return ruleBasedFallback();
}
return result.value; Prevention
- Keep OPENAI_FALLBACK_MODEL distinct and currently available so createAiJsonCompletion can recover.
- For OpenRouter free models, watch the daily quota and keep a funded backup model configured.
- Validate that OPENAI_API_URL ends in /v1 and is the REST root, not a page URL.
When it happens
Trigger: 401/403 invalid or revoked OPENAI_API_KEY; 402 insufficient credits (common with OpenRouter free quota); 404 unknown or deprecated model id in OPENAI_MODEL/OPENAI_FALLBACK_MODEL; 429 rate limit or daily free quota exhausted; 400 unsupported response_format for a model not in OPENROUTER_JSON_RESPONSE_FORMAT_MODELS; provider 5xx.
Common situations: OpenRouter free-tier daily limit hit; model renamed or retired upstream (e.g. a :free variant removed); wrong OPENAI_API_URL (custom endpoint returning HTML error pages); key without permission for the chosen model; burst traffic triggering 429.
Related errors
- AI provider returned an empty response for ${model}.
- HTTP ${response.status}
- Upstash request failed with ${response.status}
- AI response JSON must be an object.
- OPENAI_API_KEY is not configured.
AI-assisted analysis of justjavac/wechat-miniapp-radar@02a010ecea (2026-08-12).
Data as JSON: /api/errors/684c33a47d9bbdaa.
Report an issue: GitHub.