From 3e96a2b589e4a968ec30d7913b91cf478434cc87 Mon Sep 17 00:00:00 2001 From: Thomas Lammers Date: Mon, 12 Oct 2026 13:36:26 +0200 Subject: [PATCH] fix(platform): retry requests that fail to connect A connection reset during the TLS handshake raised httpx.ConnectError, which the platform retry did not cover, so one dropped connection failed the whole call. A failed connect never sends the request, so it is safe to retry for any method. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01DXskDkqHWRWgUhAzNk7ptY --- packages/uipath-platform/pyproject.toml | 2 +- packages/uipath-platform/src/uipath/platform/common/retry.py | 5 +++-- packages/uipath-platform/tests/services/test_retry.py | 4 ++++ packages/uipath-platform/uv.lock | 2 +- packages/uipath/uv.lock | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index 4699bfeeb..df2ba2732 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.2.36" +version = "0.2.37" description = "HTTP client library for programmatic access to UiPath Platform" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/packages/uipath-platform/src/uipath/platform/common/retry.py b/packages/uipath-platform/src/uipath/platform/common/retry.py index ff4b5a064..d229dd20a 100644 --- a/packages/uipath-platform/src/uipath/platform/common/retry.py +++ b/packages/uipath-platform/src/uipath/platform/common/retry.py @@ -6,7 +6,7 @@ import random -from httpx import ConnectTimeout, HTTPStatusError, Response, TimeoutException +from httpx import ConnectError, HTTPStatusError, Response, TimeoutException from tenacity import RetryCallState from ..errors import EnrichedException @@ -67,7 +67,8 @@ def extract_retry_after_from_chain(exception: BaseException) -> float | None: def is_retryable_platform_exception(exception: BaseException) -> bool: """Return True if the exception is transient and should be retried.""" - if isinstance(exception, (ConnectTimeout, TimeoutException)): + # A failed connect never sent the request, so any method is safe to retry. + if isinstance(exception, (ConnectError, TimeoutException)): return True if isinstance(exception, EnrichedException): return exception.status_code in RETRYABLE_STATUS_CODES diff --git a/packages/uipath-platform/tests/services/test_retry.py b/packages/uipath-platform/tests/services/test_retry.py index ab893f042..14d21bcc4 100644 --- a/packages/uipath-platform/tests/services/test_retry.py +++ b/packages/uipath-platform/tests/services/test_retry.py @@ -149,6 +149,10 @@ def test_timeout_exception(self): err = httpx.TimeoutException("timed out") assert is_retryable_platform_exception(err) is True + def test_connect_error(self): + err = httpx.ConnectError("[Errno 104] Connection reset by peer") + assert is_retryable_platform_exception(err) is True + def test_enriched_408(self): http_err = _make_http_status_error(408) err = EnrichedException(http_err) diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index 99070bbf4..9ada6c4ac 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1095,7 +1095,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.2.36" +version = "0.2.37" source = { editable = "." } dependencies = [ { name = "anyio" }, diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index 09541f1cc..0c4dcb200 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2762,7 +2762,7 @@ wheels = [ [[package]] name = "uipath-platform" -version = "0.2.36" +version = "0.2.37" source = { editable = "../uipath-platform" } dependencies = [ { name = "anyio" },