22
33from types import SimpleNamespace
44
5- from mcp .shared .exceptions import McpError
6- from mcp .types import ErrorData
7-
85from sap_cloud_sdk .agentgateway ._compat import (
6+ find_malformed_result_error ,
97 find_mcp_error ,
8+ make_mcp_error ,
109 mcp_input_schema ,
1110 mcp_is_error ,
1211 mcp_server_name ,
@@ -98,18 +97,18 @@ class TestFindMcpError:
9897
9998 def test_returns_bare_mcp_error (self ):
10099 """A bare McpError is returned directly."""
101- err = McpError ( ErrorData ( code = - 32602 , message = "Unknown tool: foo" ) )
100+ err = make_mcp_error ( - 32602 , "Unknown tool: foo" )
102101 assert find_mcp_error (err ) is err
103102
104103 def test_finds_mcp_error_in_group (self ):
105104 """An McpError wrapped in a BaseExceptionGroup is found."""
106- err = McpError ( ErrorData ( code = - 32603 , message = "Internal Server Error" ) )
105+ err = make_mcp_error ( - 32603 , "Internal Server Error" )
107106 group = BaseExceptionGroup ("eg" , [err ])
108107 assert find_mcp_error (group ) is err
109108
110109 def test_finds_mcp_error_in_nested_group (self ):
111110 """An McpError nested in a group within a group is found."""
112- err = McpError ( ErrorData ( code = - 32600 , message = "bad request" ) )
111+ err = make_mcp_error ( - 32600 , "bad request" )
113112 group = BaseExceptionGroup ("outer" , [BaseExceptionGroup ("inner" , [err ])])
114113 assert find_mcp_error (group ) is err
115114
@@ -121,3 +120,42 @@ def test_returns_none_without_mcp_error(self):
121120 def test_returns_none_for_unrelated_exception (self ):
122121 """A plain non-group, non-McpError exception returns None."""
123122 assert find_mcp_error (ValueError ("x" )) is None
123+
124+
125+ class TestFindMalformedResultError :
126+ """Tests for find_malformed_result_error — the isError/is_error-on-None crash."""
127+
128+ def test_returns_bare_isError_attributeerror (self ):
129+ """The mcp 1.x deref: AttributeError mentioning 'isError' is recognised."""
130+ err = AttributeError ("'NoneType' object has no attribute 'isError'" )
131+ assert find_malformed_result_error (err ) is err
132+
133+ def test_returns_bare_is_error_attributeerror (self ):
134+ """The mcp 2.x deref: AttributeError mentioning 'is_error' is recognised."""
135+ err = AttributeError ("'NoneType' object has no attribute 'is_error'" )
136+ assert find_malformed_result_error (err ) is err
137+
138+ def test_finds_attributeerror_in_group (self ):
139+ """Wrapped in a BaseExceptionGroup (anyio task group), it is still found."""
140+ err = AttributeError ("'NoneType' object has no attribute 'isError'" )
141+ group = BaseExceptionGroup ("eg" , [err ])
142+ assert find_malformed_result_error (group ) is err
143+
144+ def test_finds_attributeerror_in_nested_group (self ):
145+ """Found through nested BaseExceptionGroups."""
146+ err = AttributeError ("'NoneType' object has no attribute 'isError'" )
147+ group = BaseExceptionGroup ("outer" , [BaseExceptionGroup ("inner" , [err ])])
148+ assert find_malformed_result_error (group ) is err
149+
150+ def test_returns_none_for_unrelated_attributeerror (self ):
151+ """An AttributeError not about isError/is_error is NOT matched (not masked)."""
152+ assert find_malformed_result_error (AttributeError ("no attr 'bar'" )) is None
153+
154+ def test_returns_none_for_unrelated_exception (self ):
155+ """A non-AttributeError exception returns None."""
156+ assert find_malformed_result_error (ValueError ("x" )) is None
157+
158+ def test_returns_none_without_match_in_group (self ):
159+ """A group with no matching AttributeError leaf returns None."""
160+ group = BaseExceptionGroup ("eg" , [ValueError ("x" ), RuntimeError ("y" )])
161+ assert find_malformed_result_error (group ) is None
0 commit comments