From d0b5dd30008f72a92ecac81d3b2d864e8337cefb Mon Sep 17 00:00:00 2001 From: Xingyao Wang Date: Tue, 3 Dec 2024 10:23:31 -0600 Subject: [PATCH] feat: display exact error for runtime requests exception handling (#5386) --- openhands/runtime/action_execution_server.py | 16 ++--- openhands/runtime/utils/request.py | 62 ++++++-------------- 2 files changed, 26 insertions(+), 52 deletions(-) diff --git a/openhands/runtime/action_execution_server.py b/openhands/runtime/action_execution_server.py index ba03613dde..b48a9b55a6 100644 --- a/openhands/runtime/action_execution_server.py +++ b/openhands/runtime/action_execution_server.py @@ -14,6 +14,7 @@ import os import shutil import tempfile import time +import traceback from contextlib import asynccontextmanager from pathlib import Path from zipfile import ZipFile @@ -383,17 +384,13 @@ if __name__ == '__main__': logger.exception('Unhandled exception occurred:') return JSONResponse( status_code=500, - content={ - 'message': 'An unexpected error occurred. Please try again later.' - }, + content={'detail': 'An unexpected error occurred. Please try again later.'}, ) @app.exception_handler(StarletteHTTPException) async def http_exception_handler(request: Request, exc: StarletteHTTPException): logger.error(f'HTTP exception occurred: {exc.detail}') - return JSONResponse( - status_code=exc.status_code, content={'message': exc.detail} - ) + return JSONResponse(status_code=exc.status_code, content={'detail': exc.detail}) @app.exception_handler(RequestValidationError) async def validation_exception_handler( @@ -402,7 +399,7 @@ if __name__ == '__main__': logger.error(f'Validation error occurred: {exc}') return JSONResponse( status_code=422, - content={'message': 'Invalid request parameters', 'details': exc.errors()}, + content={'detail': 'Invalid request parameters', 'errors': exc.errors()}, ) @app.middleware('http') @@ -444,7 +441,10 @@ if __name__ == '__main__': logger.error( f'Error processing command: {str(e)}', exc_info=True, stack_info=True ) - raise HTTPException(status_code=500, detail=str(e)) + raise HTTPException( + status_code=500, + detail=traceback.format_exc(), + ) @app.post('/upload_file') async def upload_file( diff --git a/openhands/runtime/utils/request.py b/openhands/runtime/utils/request.py index 655fe304e5..f46387e96d 100644 --- a/openhands/runtime/utils/request.py +++ b/openhands/runtime/utils/request.py @@ -1,53 +1,20 @@ from typing import Any import requests -from requests.exceptions import ( - ChunkedEncodingError, - ConnectionError, -) -from urllib3.exceptions import IncompleteRead -def is_server_error(exception): - return ( - isinstance(exception, requests.HTTPError) - and exception.response.status_code >= 500 - ) +class RequestHTTPError(requests.HTTPError): + """Exception raised when an error occurs in a request with details.""" + def __init__(self, *args, detail=None, **kwargs): + super().__init__(*args, **kwargs) + self.detail = detail -def is_404_error(exception): - return ( - isinstance(exception, requests.HTTPError) - and exception.response.status_code == 404 - ) - - -def is_429_error(exception): - return ( - isinstance(exception, requests.HTTPError) - and exception.response.status_code == 429 - ) - - -def is_503_error(exception): - return ( - isinstance(exception, requests.HTTPError) - and exception.response.status_code == 503 - ) - - -def is_502_error(exception): - return ( - isinstance(exception, requests.HTTPError) - and exception.response.status_code == 502 - ) - - -DEFAULT_RETRY_EXCEPTIONS = [ - ConnectionError, - IncompleteRead, - ChunkedEncodingError, -] + def __str__(self) -> str: + s = super().__str__() + if self.detail is not None: + s += f'\nDetails: {self.detail}' + return s def send_request( @@ -58,5 +25,12 @@ def send_request( **kwargs: Any, ) -> requests.Response: response = session.request(method, url, **kwargs) - response.raise_for_status() + try: + response.raise_for_status() + except requests.HTTPError as e: + try: + _json = response.json() + except requests.JSONDecodeError: + raise e + raise RequestHTTPError(e, detail=_json.get('detail')) from e return response