From eb55d133706fffbe87c8da96bcf2fc157d322be5 Mon Sep 17 00:00:00 2001 From: Neal Richardson Date: Mon, 6 Jul 2026 12:05:27 -0400 Subject: [PATCH] Handle bad response on multipart bundle upload (#814) The multipart form path in upload_bundle (used when metadata is provided) never called handle_bad_response, so a bad HTTP response propagated as a raw HTTPResponse and caused cryptic downstream failures. Call it for both upload paths. Co-Authored-By: Claude Opus 4.8 (1M context) --- rsconnect/api.py | 2 +- tests/test_git_metadata.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/rsconnect/api.py b/rsconnect/api.py index c909a9dcb..de19647a4 100644 --- a/rsconnect/api.py +++ b/rsconnect/api.py @@ -736,7 +736,7 @@ def upload_bundle( response = cast( Union[BundleMetadata, HTTPResponse], self.post(f"v1/content/{content_guid}/bundles", body=tarball) ) - response = self._server.handle_bad_response(response) + response = self._server.handle_bad_response(response) return response def content_update(self, content_guid: str, updates: Mapping[str, str | None]) -> ContentItemV1: diff --git a/tests/test_git_metadata.py b/tests/test_git_metadata.py index c15e19fb3..0faf21b76 100644 --- a/tests/test_git_metadata.py +++ b/tests/test_git_metadata.py @@ -266,3 +266,22 @@ def test_upload_bundle_signature_accepts_metadata(self): # Check that upload_bundle has metadata parameter sig = signature(RSConnectClient.upload_bundle) assert "metadata" in sig.parameters + + def test_upload_bundle_with_metadata_handles_bad_response(self): + """A bad response on the multipart (metadata) upload path is surfaced as an + RSConnectException rather than a raw HTTPResponse (issue #814).""" + import io + from unittest.mock import patch + + from rsconnect.api import RSConnectClient, RSConnectException, RSConnectServer + from rsconnect.http_support import HTTPResponse + + client = RSConnectClient(RSConnectServer("http://test-server", "api_key")) + bad_response = HTTPResponse( + "http://test-server/__api__/v1/content/guid/bundles", + exception=OSError("connection refused"), + ) + with patch.object(RSConnectClient, "post", return_value=bad_response): + with pytest.raises(RSConnectException) as cm: + client.upload_bundle("guid", io.BytesIO(b"tarball"), metadata={"source": "git"}) + assert "connection refused" in str(cm.value)