From f19d9d05bc98a9e95d5cb3d5688c418e8bc70f6f Mon Sep 17 00:00:00 2001 From: wsxzei Date: Wed, 7 Jan 2026 17:28:53 +0800 Subject: [PATCH] fix(api): improve error message clarity in evaluation results Enhance error handling in invoke_app to display actual provider error messages instead of generic HTTP error codes. This improves user experience by showing actionable error information (e.g., "OpenAI rate limit exceeded" instead of "HTTP 429: Too Many Requests"). Changes: - Parse response detail.message/stacktrace from LLM provider errors - Preserve HTTP status code and full error response for debugging - Add detailed stacktrace extraction from multiple response formats - Improve error message prioritization (provider message > generic error) Previously, evaluation table showed ambiguous error messages that didn't explain what went wrong or how to fix it. Users can now see the actual provider error and hover for technical details. Related issue: #3324 - [UX bug] Misleading error message in evaluation table --- api/oss/src/services/llm_apps_service.py | 33 ++++++++++++++++++------ 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/api/oss/src/services/llm_apps_service.py b/api/oss/src/services/llm_apps_service.py index 858f4132f9..972041a48d 100644 --- a/api/oss/src/services/llm_apps_service.py +++ b/api/oss/src/services/llm_apps_service.py @@ -296,14 +296,31 @@ async def invoke_app( ) except aiohttp.ClientResponseError as e: - error_message = app_response.get("detail", {}).get( - "error", f"HTTP error {e.status}: {e.message}" - ) - stacktrace = app_response.get("detail", {}).get( - "message" - ) or app_response.get("detail", {}).get( - "traceback", "".join(traceback.format_exception_only(type(e), e)) - ) + detail = app_response.get("detail", {}) + + if isinstance(detail, dict): + # Get detail.message as the primary error message + if "message" in detail and detail["message"]: + error_message = detail["message"] + elif "error" in detail and detail["error"]: + error_message = detail["error"] + else: + error_message = f"HTTP error {e.status}: {e.message}" + else: + # Fallback to HTTP error info + error_message = f"HTTP error {e.status}: {e.message}" + + # Extract stacktrace from detail, fallback to exception traceback + if isinstance(detail, dict): + raw_stacktrace = (detail.get("stacktrace") or detail.get("traceback")) + if not raw_stacktrace: + stacktrace = "".join(traceback.format_exception_only(type(e), e)) + elif isinstance(raw_stacktrace, list): + stacktrace = "".join(str(item) for item in raw_stacktrace) + else: + stacktrace = str(raw_stacktrace) + else: + stacktrace = "".join(traceback.format_exception_only(type(e), e)) log.error(f"HTTP error occurred during request: {error_message}") except aiohttp.ServerTimeoutError as e: error_message = "Request timed out"