@@ -222,6 +222,39 @@ def __getitem__(self, key: str) -> object:
222222 assert exc_info .value .original_error is None
223223
224224
225+ @pytest .mark .parametrize ("runner" , [_run_scrape_tool_sync , _run_scrape_tool_async ])
226+ def test_tool_wrappers_fall_back_for_unreadable_param_value_read_keys (runner ):
227+ class _BrokenKey (str ):
228+ def __new__ (cls , value : str ):
229+ instance = super ().__new__ (cls , value )
230+ instance ._iteration_count = 0
231+ return instance
232+
233+ def __iter__ (self ):
234+ self ._iteration_count += 1
235+ if self ._iteration_count > 1 :
236+ raise RuntimeError ("cannot iterate param key" )
237+ return super ().__iter__ ()
238+
239+ class _BrokenValueMapping (Mapping [str , object ]):
240+ def __iter__ (self ) -> Iterator [str ]:
241+ yield _BrokenKey ("url" )
242+
243+ def __len__ (self ) -> int :
244+ return 1
245+
246+ def __getitem__ (self , key : str ) -> object :
247+ _ = key
248+ raise RuntimeError ("cannot read value" )
249+
250+ with pytest .raises (
251+ HyperbrowserError , match = "Failed to read tool param '<unreadable key>'"
252+ ) as exc_info :
253+ runner (_BrokenValueMapping ())
254+
255+ assert isinstance (exc_info .value .original_error , RuntimeError )
256+
257+
225258@pytest .mark .parametrize ("runner" , [_run_scrape_tool_sync , _run_scrape_tool_async ])
226259def test_tool_wrappers_wrap_param_key_strip_failures (runner ):
227260 class _BrokenStripKey (str ):
0 commit comments