Skip to content

fix(auth): preserve status context for non-JSON 5xx errors - #1312

Open
mmarufov wants to merge 1 commit into
supabase:mainfrom
mmarufov:fix/auth-non-json-status-message
Open

mmarufov wants to merge 1 commit into
supabase:mainfrom
mmarufov:fix/auth-non-json-status-message

Conversation

@mmarufov

@mmarufov mmarufov commented Sep 3, 2026

Copy link
Copy Markdown

Summary

  • preserve useful HTTP status context when an Auth error body is not valid JSON
  • fall back to HTTP <status>: <status description> for 5xx responses, e.g. HTTP 503: service unavailable
  • retain existing structured JSON error behavior, and the existing Unexpected error message for undecodable non-5xx responses

Why

Non-JSON proxy/server failures (an HTML error page from a load balancer, an empty body) currently collapse to Unexpected error, hiding the only actionable context available to callers. This is the Swift side of the supabase-js change in supabase/supabase-js#2587; the Dart (supabase/supabase-flutter#1653) and Kotlin (supabase-community/supabase-kt#1379) SDKs already landed equivalents.

Fixes #1171.

Design notes

  • HTTPURLResponse does not expose the reason phrase on any platform, so the closest analog is HTTPURLResponse.localizedString(forStatusCode:), which RealtimeChannelV2 already uses for the same purpose.
  • That description is localized on Darwin (internal server error) and is capitalized English on Linux (Internal Server Error), so the status code is always included to keep a deterministic core in the message. Happy to switch to the bare description if you prefer strict parity with the JS shape.
  • The description is never empty in the 5xx range on either platform; the empty check is defensive only.
  • Scoped to 5xx to match the issue title and the Dart fix. Undecodable 4xx bodies keep the existing Unexpected error message.
  • No public API changes. errorCode, underlyingData, and underlyingResponse are unchanged.

Tests

New Tests/AuthTests/APIClientTests.swift:

  • nonJSONServerErrorUsesStatusCodeAndDescription: HTML 500 body yields HTTP 500: <description> and preserves error code, data, and underlying response
  • nonJSONServerErrorWithEmptyBodyPreservesStatusCode: empty 503 body yields HTTP 503: <description>
  • nonJSONServerErrorUpperBoundaryPreservesStatusCode: 599 boundary
  • jsonErrorKeepsServerMessage: JSON 500 body still returns the server message
  • nonJSONErrorOutsideServerRangeKeepsExistingFallback (400, 499, 600): unchanged Unexpected error

Marufov and Muhammadjon were added to dictionary.txt for the test file header, following the existing convention for author names.

Verification

  • swift test --filter APIClientTests on unpatched main (test file copied in): 3 of 5 fail with Unexpected error
  • swift test --filter APIClientTests on this branch: 5 of 5 pass
  • swift test --filter AuthTests --skip IntegrationTests: 315 tests in 25 suites pass
  • ./scripts/format.sh equivalent on changed files: no diff; swift-format lint --strict: clean
  • ./scripts/spell-check.sh: 0 issues

`APIClient.handleError` returned the generic "Unexpected error" whenever
the body could not be decoded as `_RawAPIErrorResponse`, hiding the only
actionable context a non-JSON 5xx response (proxy HTML page, empty body)
carries.

`HTTPURLResponse` does not expose the reason phrase, so the fallback now
uses `HTTP <status>: <status description>` for 5xx responses, where the
description comes from `HTTPURLResponse.localizedString(forStatusCode:)`.
The status code is always included because the description is localized
on Darwin and differs from the Linux one. Undecodable non-5xx responses
keep the existing "Unexpected error" message, and JSON error bodies are
unaffected.

Fixes supabase#1171
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 8a72ce95-8619-4c15-bfb6-99244f482ae8

📥 Commits

Reviewing files that changed from the base of the PR and between 3204541 and a5310ea.

📒 Files selected for processing (3)
  • Sources/Auth/Internal/APIClient.swift
  • Tests/AuthTests/APIClientTests.swift
  • dictionary.txt

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Summary

Summary by CodeRabbit

  • Bug Fixes

    • Improved server-error messages to include the HTTP status code and localized description for 5xx responses.
    • Preserved server-provided messages for JSON error responses and retained generic messaging for other unexpected errors.
    • Added support for networking functionality across supported platforms.
  • Chores

    • Updated spell-checking support for additional names.

Walkthrough

APIClient.handleError(response:) now includes the HTTP status code and localized status description for non-JSON 5xx responses. Other unexpected errors retain the "Unexpected error" message. New tests cover status boundaries, empty and HTML bodies, JSON error messages, and response preservation. FoundationNetworking is imported conditionally. The spell-check dictionary adds two entries.

Assessment against linked issues

Objective Addressed Explanation
Preserve status information for non-JSON 5xx responses, including a synthesized HTTP <status> fallback [#1171]
Keep JSON error parsing and existing public API behavior unchanged [#1171]
Add unit tests for the expected and boundary cases [#1171]
Update documentation [#1171] No documentation changes are included.

Merge Risk: ⚪ Minimal · up to a5310

Auth errors from non-JSON 5xx responses now retain HTTP status context while structured JSON errors and existing non-5xx fallback behavior remain unchanged. Coverage includes HTML, empty-body, boundary, and preservation cases, leaving no actionable merge risk.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Warning

⚠️ This pull request has been flagged as potential spam (contributor-gaming) by CodeRabbit slop detection and should be reviewed carefully.

@mmarufov
mmarufov marked this pull request as ready for review September 3, 2026 00:58
@mmarufov
mmarufov requested review from a team and grdsdev as code owners September 3, 2026 00:58

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

parity(auth): preserve HTTP status text on non-JSON 5xx error responses [from supabase-js]

1 participant