feat(pipeline-run): surface API HTTP failures as clean errors#38
feat(pipeline-run): surface API HTTP failures as clean errors#38arseniy-pplx wants to merge 1 commit into
Conversation
| return f"Tangle API request failed: {exc}" | ||
| request = response.request | ||
| target = ( | ||
| f"{request.method} {request.url}" |
There was a problem hiding this comment.
(AI-assisted)
Please redact the request URL and backend detail before rendering this error.
This currently interpolates both request.url and response.text verbatim. For example, formatting a request to https://alice:hunter2@api.test/x?access_token=QUERYSECRET with an error body containing credential=BODYSECRET exposes all three values in the resulting stderr line.
Could we sanitize URL userinfo/credential query parameters and pass structured response bodies through the existing sensitive-key redaction before truncation? Ideally the requests/httpx error paths in #38, #45, and #46 should share transport-neutral redaction helpers so their guarantees do not drift.
Volv-G
left a comment
There was a problem hiding this comment.
(AI-assisted)
Approved per reviewer direction. The inline credential-redaction feedback remains available for follow-up.
3d0c42a to
0f8300e
Compare
Pipeline-run SDK commands leaked raw requests tracebacks whenever the API answered non-2xx. Manager and annotation methods that call the client now run under a shared error-surfacing context manager that re-raises requests.HTTPError as PipelineRunError with the status, reason, method, URL and a single-line, trimmed response body, so sdk pipeline-runs commands (including submit and annotations) exit non-zero with a one-line message. Client-internal recovery such as the 404 run-id to execution-id fallback and post-submit run recovery keeps handling the statuses it can; per-run graph-state failures reuse the formatted message in each result's error field. on_poll_error and on_submit_error hooks now receive PipelineRunError with the original HTTPError chained as __cause__. Harden the shared redaction so echoed URLs and bodies cannot leak credentials: URL query redaction now also covers presigned/SAS signature keys (signature, X-Amz-Signature, sig, awsaccesskeyid, googleaccessid) and bare api_key, matching the sibling transport helper so the guarantees do not drift; and non-JSON response bodies (form-encoded, plain text, HTML) now have recognizable credential key=value / key: value assignments redacted, with the ambiguous colon form gated to opaque-looking values so natural-language detail is preserved.
0f8300e to
a90101c
Compare
Summary
surface_http_errorscontext manager for SDK commandssignature,X-Amz-Signature,sig,awsaccesskeyid,googleaccessid) and bareapi_key, kept in sync with the sibling transport helper so the guarantees do not driftkey=value/key: valuecredential assignments in non-JSON bodies (form-encoded, plain text, HTML); the ambiguous colon form is gated to opaque-looking values so non-sensitive keys (page=2) and natural-language detail (credential: invalid) are preservederrorfieldContext
Pipeline-run SDK commands currently leak raw
requeststracebacks when the API returns a non-2xx response. The command layer already convertsPipelineRunErrorto a clean non-zero exit; this change makes HTTP failures onsdk pipeline-runscommands cross that boundary instead. Client-internal recovery (the 404 run-id -> execution-id fallback, submission-id run recovery after a failed submit) keeps handling the statuses it can; only unrecovered errors are formatted.Behavior note for downstream hook subclasses:
on_poll_errorandon_submit_errornow receivePipelineRunError(with the originalrequests.HTTPErrorchained as__cause__) instead of the rawHTTPErrorwhen an API call fails with an HTTP status error. Non-HTTP submit errors reachon_submit_errorunchanged.Testing
uv run pytest tests/test_sdk_http_errors.py tests/test_pipeline_runs_cli.pyuvx ruff checkon the touched source filesuv lock --checkgit diff --check