Fix tool call validation error handling for Groq LLM provider (#10927)

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
This commit is contained in:
Engel Nyst 2025-12-19 07:31:07 +01:00 committed by GitHub
parent 88c053b23c
commit ec9daf3bcc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 66 additions and 0 deletions

View File

@ -944,6 +944,23 @@ class AgentController:
return
else:
raise LLMContextWindowExceedError()
# Check if this is a tool call validation error that should be recoverable
elif (
isinstance(e, BadRequestError)
and 'tool call validation failed' in error_str
and (
'missing properties' in error_str
or 'missing required' in error_str
)
):
# Handle tool call validation errors from Groq as recoverable errors
self.event_stream.add_event(
ErrorObservation(
content=f'Tool call validation failed: {str(e)}. Please check the tool parameters and try again.',
),
EventSource.AGENT,
)
return
else:
raise e

View File

@ -299,6 +299,55 @@ async def test_react_to_content_policy_violation(
await controller.close()
@pytest.mark.asyncio
async def test_tool_call_validation_error_handling(
mock_agent_with_stats,
test_event_stream,
):
"""Test that tool call validation errors from Groq are handled as recoverable errors."""
mock_agent, conversation_stats, llm_registry = mock_agent_with_stats
controller = AgentController(
agent=mock_agent,
event_stream=test_event_stream,
conversation_stats=conversation_stats,
iteration_delta=10,
sid='test',
confirmation_mode=False,
headless_mode=True,
)
controller.state.agent_state = AgentState.RUNNING
# Mock the agent.step method to raise a BadRequestError with tool validation failure
def mock_step(state):
raise BadRequestError(
message='litellm.BadRequestError: GroqException - {"error":{"message":"tool call validation failed: parameters for tool str_replace_editor did not match schema: errors: [missing properties: \'path\']","type":"invalid_request_error","code":"tool_use_failed"}}',
model='groq/llama3-8b-8192',
llm_provider='groq',
)
mock_agent.step = mock_step
# Call _step which should handle the tool validation error
await controller._step()
# Verify that the agent state is still RUNNING (not ERROR)
assert controller.state.agent_state == AgentState.RUNNING
# Verify that an ErrorObservation was added to the event stream
events = list(test_event_stream.get_events())
error_observations = [e for e in events if isinstance(e, ErrorObservation)]
assert len(error_observations) == 1
error_obs = error_observations[0]
assert 'tool call validation failed' in error_obs.content
assert 'missing properties' in error_obs.content
assert 'path' in error_obs.content
await controller.close()
@pytest.mark.asyncio
async def test_run_controller_with_fatal_error(
test_event_stream, mock_memory, mock_agent_with_stats