From 2cfee80395cef60589b091609daae8de8f739fcd Mon Sep 17 00:00:00 2001 From: Bruno Gale Date: Tue, 29 Sep 2026 23:06:37 +0200 Subject: [PATCH] fix(storage): throw a SupabaseStorageException for a non-JSON 2xx body --- .../Files/StorageFileApiContractTests.cs | 16 ++++++++++++++++ packages/Storage/Storage/Helpers.cs | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/packages/Storage/Storage.Tests/Files/StorageFileApiContractTests.cs b/packages/Storage/Storage.Tests/Files/StorageFileApiContractTests.cs index 55d7a5b7..b71c1f47 100644 --- a/packages/Storage/Storage.Tests/Files/StorageFileApiContractTests.cs +++ b/packages/Storage/Storage.Tests/Files/StorageFileApiContractTests.cs @@ -392,6 +392,22 @@ public async Task List_ShouldSurfaceStorageException_GivenNonJsonError() } } + [TestMethod] + public async Task List_ShouldSurfaceStorageException_GivenNonJsonSuccessBody() + { + const string body = "502 Bad Gateway"; + this.server.Given(Request.Create().WithPath($"/storage/v1/object/list/{Bucket}").UsingPost()) + .RespondWith(Response.Create().WithStatusCode(200).WithBody(body)); + var act = () => this.client.From(Bucket).List(); + var exception = (await act.Should().ThrowAsync( + "storage-js reports a non-JSON 2xx body as a StorageUnknownError, not a raw parse error")).Which; + using (new AssertionScope()) + { + exception.StatusCode.Should().Be(200); + exception.Content.Should().Be(body); + } + } + [TestMethod] public async Task UploadToSignedUrl_ShouldForwardMetadataAndCustomHeaders_GivenFileOptions() { diff --git a/packages/Storage/Storage/Helpers.cs b/packages/Storage/Storage/Helpers.cs index 723c201e..2c694701 100644 --- a/packages/Storage/Storage/Helpers.cs +++ b/packages/Storage/Storage/Helpers.cs @@ -74,6 +74,21 @@ internal static HttpClient ResolveDownloadClient(ClientOptions options) => var response = await MakeRequestAsync(httpClient, retry, method, url, data, headers, cancellationToken); var content = await response.Content.ReadAsStringAsync(); + // A proxy can answer 2xx with an HTML page; JSON that doesn't fit T still throws below. + try + { + JsonDocument.Parse(content).Dispose(); + } + catch (JsonException e) + { + throw new SupabaseStorageException(e.Message, e) + { + Content = content, + Response = response, + StatusCode = (int) response.StatusCode, + }; + } + return JsonSerializer.Deserialize(content, SerializerOptions); }