#1620

[BUG] Cloud downloads raise an uncaught exception when an HTTP error body is interrupted

Opensamirhvbropened 9d ago

Describe the bug

Cloud downloads use streamed responses. When the server returns an HTTP error and the connection is interrupted while reading its error body, requests.exceptions.ChunkedEncodingError escapes the CLI instead of producing its usual error output and return code.

This affects the shared download path used by reports, SARIF, file archives, and audit exports. For example, an automation using scans report --output report.pdf --json gets a traceback rather than a JSON error when a 503 response is truncated. Redirected binary output should likewise keep diagnostics on stderr.

To Reproduce

Confirmed on current main, 6b7ae2ebe4d47037a927aade23265ff4e4f27e84, with Python 3.12.14 and the frozen dependencies (Requests 2.34.2, urllib3 2.7.0). No cloud account or LLM is needed: this feeds the real Requests/urllib3 body reader an incomplete response and mocks only the HTTP request.

import io
import tempfile
from pathlib import Path
from unittest.mock import patch

import requests
from urllib3.response import HTTPResponse

from strix.interface import cloud

response = requests.Response()
response.status_code = 503
response.headers["Content-Type"] = "application/json"
response.raw = HTTPResponse(
    body=io.BytesIO(b'{"error":'),
    headers={"Content-Length": "100"},
    preload_content=False,
    enforce_content_length=True,
)
with tempfile.TemporaryDirectory() as directory:
    output = Path(directory) / "report.pdf"
    with patch("requests.request", return_value=response):
        cloud.run_cloud([
            "scans", "report", "scan-1", "--token", "synthetic-token",
            "--output", str(output), "--json",
        ])

Actual result:

requests.exceptions.ChunkedEncodingError:
('Connection broken: IncompleteRead(9 bytes read, 91 more expected)', ...)

The same failure happens with a truncated text error body. Normal successful download-body failures are already handled; the missing boundary is the call to http.check(response) before writing the download.

Expected behavior and proposed change

Return the normal cloud transport error (exit 1), produce JSON when downloading to a file with --json, and keep diagnostics on stderr when stdout carries raw download bytes. The response should still close and an existing output file should remain untouched.

Convert Requests body-read exceptions while parsing the response in http.check to CloudTransportError. Add regression coverage through the CLI with real Requests/urllib3 response objects, for JSON and text error bodies and both output modes. No automatic retry or change to timeout policy is needed.

System Information:

  • OS: macOS
  • Strix commit: 6b7ae2ebe4d47037a927aade23265ff4e4f27e84
  • Python: 3.12.14, frozen project dependencies
  • LLM: none

Additional context

Validation so far is local and synthetic; I have not induced an error on the live managed service. The current issue/PR history, including the cloud CLI implementation in #1177, has no equivalent fix.

Activity

0

No activity yet.