@@ -30,6 +30,17 @@ class _NonRetryablePollingError(HyperbrowserError):
3030 pass
3131
3232
33+ def _safe_exception_text (exc : Exception ) -> str :
34+ try :
35+ return str (exc )
36+ except Exception :
37+ return f"<unstringifiable { type (exc ).__name__ } >"
38+
39+
40+ def _normalized_exception_text (exc : Exception ) -> str :
41+ return _safe_exception_text (exc ).lower ()
42+
43+
3344def _coerce_operation_name_component (value : object , * , fallback : str ) -> str :
3445 if isinstance (value , str ):
3546 return value
@@ -206,21 +217,21 @@ def _invoke_non_retryable_callback(
206217 raise
207218 except Exception as exc :
208219 raise _NonRetryablePollingError (
209- f"{ callback_name } failed for { operation_name } : { exc } "
220+ f"{ callback_name } failed for { operation_name } : { _safe_exception_text ( exc ) } "
210221 ) from exc
211222
212223
213224def _is_reused_coroutine_runtime_error (exc : Exception ) -> bool :
214225 if not isinstance (exc , RuntimeError ):
215226 return False
216- normalized_message = str (exc ). lower ( )
227+ normalized_message = _normalized_exception_text (exc )
217228 return "coroutine" in normalized_message and "already awaited" in normalized_message
218229
219230
220231def _is_async_generator_reuse_runtime_error (exc : Exception ) -> bool :
221232 if not isinstance (exc , RuntimeError ):
222233 return False
223- normalized_message = str (exc ). lower ( )
234+ normalized_message = _normalized_exception_text (exc )
224235 return (
225236 "asynchronous generator" in normalized_message
226237 and "already running" in normalized_message
@@ -230,13 +241,13 @@ def _is_async_generator_reuse_runtime_error(exc: Exception) -> bool:
230241def _is_generator_reentrancy_error (exc : Exception ) -> bool :
231242 if not isinstance (exc , ValueError ):
232243 return False
233- return "generator already executing" in str (exc ). lower ( )
244+ return "generator already executing" in _normalized_exception_text (exc )
234245
235246
236247def _is_async_loop_contract_runtime_error (exc : Exception ) -> bool :
237248 if not isinstance (exc , RuntimeError ):
238249 return False
239- normalized_message = str (exc ). lower ( )
250+ normalized_message = _normalized_exception_text (exc )
240251 if "event loop is closed" in normalized_message :
241252 return True
242253 if "event loop other than the current one" in normalized_message :
@@ -253,7 +264,7 @@ def _is_async_loop_contract_runtime_error(exc: Exception) -> bool:
253264def _is_executor_shutdown_runtime_error (exc : Exception ) -> bool :
254265 if not isinstance (exc , RuntimeError ):
255266 return False
256- normalized_message = str (exc ). lower ( )
267+ normalized_message = _normalized_exception_text (exc )
257268 return (
258269 "cannot schedule new futures after" in normalized_message
259270 and "shutdown" in normalized_message
@@ -445,7 +456,9 @@ def poll_until_terminal_status(
445456 failures += 1
446457 if failures >= max_status_failures :
447458 raise HyperbrowserPollingError (
448- f"Failed to poll { operation_name } after { max_status_failures } attempts: { exc } "
459+ "Failed to poll "
460+ f"{ operation_name } after { max_status_failures } attempts: "
461+ f"{ _safe_exception_text (exc )} "
449462 ) from exc
450463 if has_exceeded_max_wait (start_time , max_wait_seconds ):
451464 raise HyperbrowserTimeoutError (
@@ -494,7 +507,8 @@ def retry_operation(
494507 failures += 1
495508 if failures >= max_attempts :
496509 raise HyperbrowserError (
497- f"{ operation_name } failed after { max_attempts } attempts: { exc } "
510+ f"{ operation_name } failed after { max_attempts } attempts: "
511+ f"{ _safe_exception_text (exc )} "
498512 ) from exc
499513 time .sleep (retry_delay_seconds )
500514 continue
@@ -536,7 +550,9 @@ async def poll_until_terminal_status_async(
536550 failures += 1
537551 if failures >= max_status_failures :
538552 raise HyperbrowserPollingError (
539- f"Failed to poll { operation_name } after { max_status_failures } attempts: { exc } "
553+ "Failed to poll "
554+ f"{ operation_name } after { max_status_failures } attempts: "
555+ f"{ _safe_exception_text (exc )} "
540556 ) from exc
541557 if has_exceeded_max_wait (start_time , max_wait_seconds ):
542558 raise HyperbrowserTimeoutError (
@@ -557,7 +573,9 @@ async def poll_until_terminal_status_async(
557573 failures += 1
558574 if failures >= max_status_failures :
559575 raise HyperbrowserPollingError (
560- f"Failed to poll { operation_name } after { max_status_failures } attempts: { exc } "
576+ "Failed to poll "
577+ f"{ operation_name } after { max_status_failures } attempts: "
578+ f"{ _safe_exception_text (exc )} "
561579 ) from exc
562580 if has_exceeded_max_wait (start_time , max_wait_seconds ):
563581 raise HyperbrowserTimeoutError (
@@ -606,7 +624,8 @@ async def retry_operation_async(
606624 failures += 1
607625 if failures >= max_attempts :
608626 raise HyperbrowserError (
609- f"{ operation_name } failed after { max_attempts } attempts: { exc } "
627+ f"{ operation_name } failed after { max_attempts } attempts: "
628+ f"{ _safe_exception_text (exc )} "
610629 ) from exc
611630 await asyncio .sleep (retry_delay_seconds )
612631 continue
@@ -625,7 +644,8 @@ async def retry_operation_async(
625644 failures += 1
626645 if failures >= max_attempts :
627646 raise HyperbrowserError (
628- f"{ operation_name } failed after { max_attempts } attempts: { exc } "
647+ f"{ operation_name } failed after { max_attempts } attempts: "
648+ f"{ _safe_exception_text (exc )} "
629649 ) from exc
630650 await asyncio .sleep (retry_delay_seconds )
631651
@@ -726,7 +746,9 @@ def collect_paginated_results(
726746 failures += 1
727747 if failures >= max_attempts :
728748 raise HyperbrowserError (
729- f"Failed to fetch page batch { current_page_batch + 1 } for { operation_name } after { max_attempts } attempts: { exc } "
749+ "Failed to fetch page batch "
750+ f"{ current_page_batch + 1 } for { operation_name } after "
751+ f"{ max_attempts } attempts: { _safe_exception_text (exc )} "
730752 ) from exc
731753 if should_sleep :
732754 if has_exceeded_max_wait (start_time , max_wait_seconds ):
@@ -833,7 +855,9 @@ async def collect_paginated_results_async(
833855 failures += 1
834856 if failures >= max_attempts :
835857 raise HyperbrowserError (
836- f"Failed to fetch page batch { current_page_batch + 1 } for { operation_name } after { max_attempts } attempts: { exc } "
858+ "Failed to fetch page batch "
859+ f"{ current_page_batch + 1 } for { operation_name } after "
860+ f"{ max_attempts } attempts: { _safe_exception_text (exc )} "
837861 ) from exc
838862 if should_sleep :
839863 if has_exceeded_max_wait (start_time , max_wait_seconds ):
0 commit comments