@@ -5,6 +5,7 @@ import { formatErrorMessage } from "../../infra/errors.js";
|
5 | 5 | /** Provider request error classes that get a specialized user-facing reply. */ |
6 | 6 | export type ProviderRequestErrorCode = |
7 | 7 | | "provider_conversation_state_error" |
| 8 | +| "provider_internal_error" |
8 | 9 | | "provider_rate_limit_or_quota_error"; |
9 | 10 | |
10 | 11 | /** Structured provider error classification for reply failure handling. */ |
@@ -21,6 +22,9 @@ export const PROVIDER_CONVERSATION_STATE_ERROR_USER_MESSAGE =
|
21 | 22 | export const PROVIDER_RATE_LIMIT_OR_QUOTA_ERROR_USER_MESSAGE = |
22 | 23 | "⚠️ The model provider returned HTTP 429 before replying. This can mean rate limiting, exhausted quota, or an account balance/billing issue. Check the selected provider/model, API key, and provider billing/quota dashboard, then try again."; |
23 | 24 | |
| 25 | +export const PROVIDER_INTERNAL_ERROR_USER_MESSAGE = |
| 26 | +"⚠️ The model provider returned a temporary internal error before replying. Try again in a moment, or switch to another model if it keeps happening."; |
| 27 | + |
24 | 28 | /** Classifies provider request failures that are actionable for users. */ |
25 | 29 | export function classifyProviderRequestError( |
26 | 30 | err: unknown, |
@@ -43,6 +47,13 @@ export function classifyProviderRequestError(
|
43 | 47 | technicalMessage, |
44 | 48 | }; |
45 | 49 | } |
| 50 | +if (isProviderInternalErrorMessage(technicalMessage)) { |
| 51 | +return { |
| 52 | +code: "provider_internal_error", |
| 53 | +userMessage: PROVIDER_INTERNAL_ERROR_USER_MESSAGE, |
| 54 | + technicalMessage, |
| 55 | +}; |
| 56 | +} |
46 | 57 | return undefined; |
47 | 58 | } |
48 | 59 | |
@@ -69,6 +80,16 @@ function isGenericProviderRuntimeErrorMessage(message: string): boolean {
|
69 | 80 | ); |
70 | 81 | } |
71 | 82 | |
| 83 | +function isProviderInternalErrorMessage(message: string): boolean { |
| 84 | +const lower = normalizeLowercaseStringOrEmpty(message); |
| 85 | +return ( |
| 86 | +lower.includes("the ai service returned an internal error") || |
| 87 | +lower.includes("provider returned an internal error") || |
| 88 | +(isGenericProviderRuntimeErrorMessage(message) && |
| 89 | +(lower.includes("server_error") || lower.includes("internal error"))) |
| 90 | +); |
| 91 | +} |
| 92 | + |
72 | 93 | function hasHttp429Evidence(err: unknown, message: string): boolean { |
73 | 94 | return ( |
74 | 95 | readHttp429Status(err) || |
|