MCPcopy
hub / github.com/coder/mux / categorizeError

Method categorizeError

src/node/services/streamManager.ts:3451–3615  ·  view source on GitHub ↗

* Categorizes errors for better error handling (used for event emission)

(error: unknown)

Source from the content-addressed store, hash-verified

3449 * Categorizes errors for better error handling (used for event emission)
3450 */
3451 private categorizeError(error: unknown): StreamErrorType {
3452 if (error instanceof StreamTruncatedError) {
3453 return "stream_truncated";
3454 }
3455
3456 // Use AI SDK error type guards first
3457 if (LoadAPIKeyError.isInstance(error)) {
3458 return "authentication";
3459 }
3460 if (APICallError.isInstance(error)) {
3461 if (error.statusCode === 401) return "authentication";
3462 // 402 (Payment Required) is used by mux gateway for billing/credits issues
3463 // (e.g. "Insufficient balance. Please add credits to continue.").
3464 // Treat as non-retryable quota. Some providers also encode quota failures as
3465 // 429, so classify 429 by payload intent instead of status code alone.
3466 if (error.statusCode === 402) return "quota";
3467 if (error.statusCode === 429) {
3468 return classify429Capacity({
3469 message: error.message,
3470 data: error.data,
3471 responseBody: error.responseBody,
3472 });
3473 }
3474 if (error.statusCode && error.statusCode >= 500) return "server_error";
3475
3476 // Check for model_not_found errors (OpenAI and Anthropic)
3477 // Type guard for error data structure
3478 const hasErrorProperty = (
3479 data: unknown
3480 ): data is { error: { code?: string; type?: string } } => {
3481 return (
3482 typeof data === "object" &&
3483 data !== null &&
3484 "error" in data &&
3485 typeof data.error === "object" &&
3486 data.error !== null
3487 );
3488 };
3489
3490 // OpenAI: 400 with error.code === 'model_not_found'
3491 const isOpenAIModelError =
3492 error.statusCode === 400 &&
3493 hasErrorProperty(error.data) &&
3494 error.data.error.code === "model_not_found";
3495
3496 // Anthropic: 404 with error.type === 'not_found_error'
3497 const isAnthropicModelError =
3498 error.statusCode === 404 &&
3499 hasErrorProperty(error.data) &&
3500 error.data.error.type === "not_found_error";
3501
3502 if (isOpenAIModelError || isAnthropicModelError) {
3503 return "model_not_found";
3504 }
3505
3506 // Check for context exceeded errors (Anthropic + OpenAI-compatible / Copilot)
3507 const msgLower = error.message.toLowerCase();
3508

Callers 1

Calls 2

classify429CapacityFunction · 0.90
isStreamTruncatedMessageFunction · 0.85

Tested by

no test coverage detected