Stop flagging snake_case is_error results as tool errors in OTel span

Merged
KL
5mo ago
+12-5

Follow-up to #2970.

OpenTelemetryMiddleware matched three result shapes as a tool error: CallToolResult(is_error=True), {"isError": True}, and {"is_error": True}. The snake_case dict arm is wrong: serialize_server_result validates the handler result with by_name=False (alias-only), so a snake_case is_error key is silently dropped and the client receives a success response with no isError field. The span then reported error.type=tool_error / StatusCode.ERROR for a request whose wire response was a success - false-positive error spans.

Verified against the repo's pydantic:

{'content': [], 'is_error': True}  ->  {'content': []}                   # success on the wire
{'content': [], 'isError': True}   ->  {'content': [], 'isError': True}  # real error

Only CallToolResult and the camelCase {"isError": True} dict survive serialization as wire errors, so the match now covers just those two. The previous test is repurposed to assert the snake_case shape is not flagged and that the result serializes to {"content": []}.

Thanks to the claude[bot] review on #2970 for catching this.

AI Disclaimer

This PR was developed with the assistance of either Claude or Codex. I've reviewed and verified the changes.