Render transport failures as one clean CLI line#46
Open
arseniy-pplx wants to merge 1 commit into
Open
Conversation
Connection, timeout, TLS, proxy, and mid-response failures from the static requests client previously surfaced as a full traceback that could echo proxy credentials or signed-URL query secrets. Classify these no-response transport errors into a short reason phrase and format a single, credential-safe line that includes the method and a sanitized destination (userinfo, query, and fragment stripped). Native requests exceptions stay raw through the retry and redirect layers so those layers can still classify and retry connect/timeout failures; conversion happens only at the public _send_request boundary, which wraps a surviving no-response RequestException as a TangleApiTransportError (a requests.exceptions.RequestException subclass) with the original chained as __cause__. The CLI prints one line to stderr and exits nonzero. Errors that carry an HTTP response and programmer errors are never intercepted, so status and retry handling stay intact.
arseniy-pplx
marked this pull request as ready for review
July 20, 2026 18:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Connection, timeout, TLS, proxy, and mid-response failures from the static requests client previously bubbled up as a full Python traceback. Besides being noisy, the raw exception text can embed proxy credentials (userinfo) or signed-URL query secrets, so it was also a disclosure risk. This change turns those no-response transport failures into a single, credential-safe line.
api_transport.pyadds three reusable helpers:sanitize_destination()reduces a URL toscheme://host[:port]/path(dropping userinfo, query, and fragment; IPv6 literals re-bracketed so[2001:db8::1]:8443stays a valid origin);transport_error_reason()maps arequeststransport exception to a short phrase (e.g.TLS verification failed,connection timed out,connection closed mid-response), most-specific type first;format_transport_error()composesCould not reach Tangle API (<METHOD> <destination>): <reason>without echoing raw exception text.client.pyperforms the conversion at a single public boundary,_send_request(), which wraps_make_request(). A no-responseRequestExceptionthat survives every layer becomes aTangleApiTransportError(arequests.exceptions.RequestExceptionsubclass) carrying the formatted line, with the original chained as__cause__._make_request()and the rate-limit/redirect layers beneath it re-raise the originalrequestsexception subtypes untouched, so a lower retry layer can still classify connect/timeout failures. Errors that carry an HTTP response are re-raised unchanged, so status and retry handling are untouched.component_inspector.pyroutes its direct request through_send_request()for the same clean-error treatment.cli.pyprints the one-line message to stderr and exits nonzero at arun()boundary. It only intercepts transport failures (no response); HTTP status errors and ordinary programmer errors propagate as before, and it also formats a raw transport exception that bypassed the client.Context
Redaction, method, and sanitized destination are applied consistently across every static-client command (pipeline-runs, artifacts, components, pipelines, published-components, secrets) because they all route through the same
_send_request()boundary.Testing
uv run pytest tests/test_transport_errors.py tests/test_packaging.pycovering URL sanitization (userinfo, query including signed-URL params, fragment), IPv6 re-bracketing, reason classification (SSL/proxy/connect-timeout/read-timeout/timeout/chunked/connection/generic), the formatter never echoing raw secret-bearing text, the inner redirect strategy and_make_requestre-raising the rawrequestssubtype unchanged,_send_requestconverting toTangleApiTransportErrorwith__cause__preserved, HTTP-response errors re-raised unchanged (programmer errors not swallowed), a genuinely refused localhost port yielding a clean domain error, and the CLI rendering one stderr line with a nonzero exituvx ruff checkon the touched filesuv lock --check; wheel buildgit diff --check