From dc1e9d158e7cef011efcc08e0a5821b5415452c9 Mon Sep 17 00:00:00 2001 From: Colin L Date: Wed, 29 Apr 2026 17:46:54 -0700 Subject: [PATCH] fix: differentiate model-not-found from auth/rate errors in /test-connection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, a 404 "Model not found" from the upstream provider returned generic suggestions about checking the API key, permissions, and rate limits — none of which were the actual problem. This was specifically misleading when the proxy's bundled .env.example pinned a retired model: the user's key and permissions were fine, the model just no longer existed on their provider. Now we pattern-match on the upstream error message and return suggestions that match the failure mode: - 404 / "not found" -> point at BIG/MIDDLE/SMALL/VISION_MODEL config and link to GET /models for verification - 401 / 403 / unauth -> auth-key suggestions (the original default) - 429 / "rate" -> rate-limit suggestions - anything else -> the original generic three-line suggestion list The error 'message' field still contains the raw upstream string, so the existing diagnostic information is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/api/endpoints.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/api/endpoints.py b/src/api/endpoints.py index 455e8066..848c5677 100644 --- a/src/api/endpoints.py +++ b/src/api/endpoints.py @@ -407,18 +407,41 @@ async def test_connection(): except Exception as e: logger.error(f"API connectivity test failed: {e}") + msg = str(e) + msg_l = msg.lower() + + if "404" in msg or "not found" in msg_l or "does not exist" in msg_l: + suggestions = [ + f"The configured model '{config.small_model}' may not be available on this provider — " + f"verify against GET {config.openai_base_url.rstrip('/')}/models", + "Check BIG_MODEL, MIDDLE_MODEL, SMALL_MODEL, and VISION_MODEL in your .env", + "Token-factory providers like Nebius rotate model availability", + ] + elif "401" in msg or "403" in msg or "unauthorized" in msg_l or "forbidden" in msg_l: + suggestions = [ + "Check your OPENAI_API_KEY is valid", + "Verify your API key has the necessary permissions", + ] + elif "429" in msg or "rate" in msg_l: + suggestions = [ + "Check if you have reached rate limits", + "Wait and retry, or contact your provider about quota", + ] + else: + suggestions = [ + "Check your OPENAI_API_KEY is valid", + "Verify your API key has the necessary permissions", + "Check if you have reached rate limits", + ] + return JSONResponse( status_code=503, content={ "status": "failed", "error_type": "API Error", - "message": str(e), + "message": msg, "timestamp": datetime.now().isoformat(), - "suggestions": [ - "Check your OPENAI_API_KEY is valid", - "Verify your API key has the necessary permissions", - "Check if you have reached rate limits", - ], + "suggestions": suggestions, }, )