diff --git a/src/a2a/compat/v0_3/rest_handler.py b/src/a2a/compat/v0_3/rest_handler.py index 107e065b7..de72e5e7f 100644 --- a/src/a2a/compat/v0_3/rest_handler.py +++ b/src/a2a/compat/v0_3/rest_handler.py @@ -28,6 +28,7 @@ from a2a.compat.v0_3.request_handler import RequestHandler03 from a2a.server.context import ServerCallContext from a2a.utils import constants +from a2a.utils.errors import InvalidParamsError from a2a.utils.telemetry import SpanKind, trace_class from a2a.utils.version_validator import validate_version @@ -250,7 +251,14 @@ async def on_get_task( """ task_id = request.path_params['id'] history_length_str = request.query_params.get('historyLength') - history_length = int(history_length_str) if history_length_str else None + try: + history_length = ( + int(history_length_str) if history_length_str else None + ) + except ValueError as e: + raise InvalidParamsError( + message=f'Failed to parse historyLength field: {e}.' + ) from e rpc_req = types_v03.GetTaskRequest( id='', diff --git a/tests/compat/v0_3/test_rest_handler.py b/tests/compat/v0_3/test_rest_handler.py index 323390fed..935930191 100644 --- a/tests/compat/v0_3/test_rest_handler.py +++ b/tests/compat/v0_3/test_rest_handler.py @@ -9,6 +9,7 @@ from a2a.server.context import ServerCallContext from a2a.server.request_handlers.request_handler import RequestHandler from a2a.types.a2a_pb2 import AgentCard +from a2a.utils.errors import InvalidParamsError @pytest.fixture @@ -315,6 +316,19 @@ async def test_on_get_task(rest_handler, mock_request, mock_context): assert called_req.params.history_length == 5 +@pytest.mark.anyio +async def test_on_get_task_non_integer_history_length( + rest_handler, mock_request, mock_context +): + mock_request.path_params = {'id': 'task-1'} + mock_request.query_params = {'historyLength': 'abc'} + + with pytest.raises(InvalidParamsError): + await rest_handler.on_get_task(mock_request, mock_context) + + rest_handler.handler03.on_get_task.assert_not_called() + + @pytest.mark.anyio async def test_list_push_notifications( rest_handler, mock_request, mock_context diff --git a/tests/compat/v0_3/test_rest_routes_compat.py b/tests/compat/v0_3/test_rest_routes_compat.py index 3886e944c..8ce54ef09 100644 --- a/tests/compat/v0_3/test_rest_routes_compat.py +++ b/tests/compat/v0_3/test_rest_routes_compat.py @@ -199,6 +199,17 @@ async def test_get_task_v03( assert expected_response == actual_response +@pytest.mark.anyio +async def test_get_task_v03_non_integer_history_length( + client: AsyncClient, request_handler: MagicMock +) -> None: + response = await client.get('/v1/tasks/test_task_id?historyLength=abc') + + assert response.status_code == 400 + assert response.json()['error']['status'] == 'INVALID_ARGUMENT' + request_handler.on_get_task.assert_not_called() + + @pytest.mark.anyio async def test_list_tasks_not_in_v03_adapter_routes( request_handler: RequestHandler,