Skip to content

Commit 4d35504

Browse files
Truncate oversized polling exception messages
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent fe883cc commit 4d35504

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

hyperbrowser/client/polling.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
_FETCH_OPERATION_NAME_PREFIX = "Fetching "
2121
_FETCH_PREFIX_KEYWORD = "fetching"
2222
_TRUNCATED_OPERATION_NAME_SUFFIX = "..."
23+
_TRUNCATED_EXCEPTION_TEXT_SUFFIX = "... (truncated)"
2324
_CLIENT_ERROR_STATUS_MIN = 400
2425
_CLIENT_ERROR_STATUS_MAX = 500
2526
_RETRYABLE_CLIENT_ERROR_STATUS_CODES = {408, 429}
2627
_MAX_STATUS_CODE_TEXT_LENGTH = 6
28+
_MAX_EXCEPTION_TEXT_LENGTH = 500
2729

2830

2931
class _NonRetryablePollingError(HyperbrowserError):
@@ -36,7 +38,17 @@ def _safe_exception_text(exc: Exception) -> str:
3638
except Exception:
3739
return f"<unstringifiable {type(exc).__name__}>"
3840
if exception_message.strip():
39-
return exception_message
41+
if len(exception_message) <= _MAX_EXCEPTION_TEXT_LENGTH:
42+
return exception_message
43+
available_message_length = (
44+
_MAX_EXCEPTION_TEXT_LENGTH - len(_TRUNCATED_EXCEPTION_TEXT_SUFFIX)
45+
)
46+
if available_message_length <= 0:
47+
return _TRUNCATED_EXCEPTION_TEXT_SUFFIX
48+
return (
49+
f"{exception_message[:available_message_length]}"
50+
f"{_TRUNCATED_EXCEPTION_TEXT_SUFFIX}"
51+
)
4052
return f"<{type(exc).__name__}>"
4153

4254

tests/test_polling.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6750,3 +6750,39 @@ def test_retry_operation_uses_placeholder_for_blank_error_messages():
67506750
max_attempts=1,
67516751
retry_delay_seconds=0.0,
67526752
)
6753+
6754+
6755+
def test_poll_until_terminal_status_truncates_oversized_error_messages():
6756+
very_long_message = "x" * 2000
6757+
6758+
with pytest.raises(
6759+
HyperbrowserPollingError,
6760+
match=r"Failed to poll long-error poll after 1 attempts: .+\.\.\. \(truncated\)",
6761+
) as exc_info:
6762+
poll_until_terminal_status(
6763+
operation_name="long-error poll",
6764+
get_status=lambda: (_ for _ in ()).throw(RuntimeError(very_long_message)),
6765+
is_terminal_status=lambda value: value == "completed",
6766+
poll_interval_seconds=0.0,
6767+
max_wait_seconds=1.0,
6768+
max_status_failures=1,
6769+
)
6770+
6771+
assert "... (truncated)" in str(exc_info.value)
6772+
6773+
6774+
def test_retry_operation_truncates_oversized_error_messages():
6775+
very_long_message = "y" * 2000
6776+
6777+
with pytest.raises(
6778+
HyperbrowserError,
6779+
match=r"long-error retry failed after 1 attempts: .+\.\.\. \(truncated\)",
6780+
) as exc_info:
6781+
retry_operation(
6782+
operation_name="long-error retry",
6783+
operation=lambda: (_ for _ in ()).throw(ValueError(very_long_message)),
6784+
max_attempts=1,
6785+
retry_delay_seconds=0.0,
6786+
)
6787+
6788+
assert "... (truncated)" in str(exc_info.value)

0 commit comments

Comments
 (0)