Skip to content

fix: parse GraphQL errors from response body on HTTP 4xx/5xx status codes#1457

Merged
jasonkuhrt merged 1 commit into
graphql-requestfrom
fix/parse-response-body-on-4xx-errors
Nov 10, 2025
Merged

fix: parse GraphQL errors from response body on HTTP 4xx/5xx status codes#1457
jasonkuhrt merged 1 commit into
graphql-requestfrom
fix/parse-response-body-on-4xx-errors

Conversation

@jasonkuhrt
Copy link
Copy Markdown
Member

Summary

Fixes regression from v6 to v7 where HTTP 4xx/5xx responses would throw ClientError without including the GraphQL errors from the response body.

Changes

  • Parse response body before checking HTTP status in runRequest.ts:74-102
  • Include parsed GraphQL response (errors + data) in ClientError when HTTP status is non-2xx
  • Add comprehensive test suite covering various HTTP error status codes (422, 500, 404, 403, 400)

Rationale

In v6, when a server returned a 4xx/5xx HTTP status with a valid GraphQL response body containing errors, users could access those errors via error.response.errors. This was a common pattern for handling authentication errors (422), server errors (500), etc.

The v7 implementation in runRequest.ts checked fetchResponse.ok before parsing the response body, which meant the GraphQL errors were never extracted and included in the ClientError. This broke user code that relied on accessing error details.

Solution

The fix moves the parseResultFromResponse() call to happen before the HTTP status check. This ensures:

  1. Response body is always parsed if it contains valid GraphQL response
  2. ClientError includes both HTTP metadata (status, headers) AND GraphQL response data (errors, data)
  3. Behavior matches v6 where errors are accessible regardless of HTTP status

Test Plan

  • ✅ All existing tests pass (75 tests)
  • ✅ New test suite with 5 test cases covering:
    • 422 status with GraphQL errors + data
    • 500 status with GraphQL errors only
    • 404 status with GraphQL errors
    • 403 status with partial data + errors
    • 400 status with validation errors

Closes #1281

…odes

Fixes regression from v6 to v7 where HTTP 4xx/5xx responses would throw
ClientError without including the GraphQL errors from the response body.

Changes:
- Parse response body BEFORE checking HTTP status in runRequest.ts
- Include parsed GraphQL response data in ClientError when status is non-2xx
- Add comprehensive test suite for various HTTP error status codes (422, 500, 404, 403, 400)

This restores the v6 behavior where users can access response.errors even
when the server returns a non-2xx HTTP status code.

Closes #1281
@jasonkuhrt jasonkuhrt force-pushed the fix/parse-response-body-on-4xx-errors branch from 2bb27f2 to f93bdca Compare November 10, 2025 18:09
@jasonkuhrt jasonkuhrt merged commit 7a1ee76 into graphql-request Nov 10, 2025
8 checks passed
@jasonkuhrt jasonkuhrt deleted the fix/parse-response-body-on-4xx-errors branch November 10, 2025 18:10
jasonkuhrt added a commit that referenced this pull request Nov 11, 2025
Fixes #1458

PR #1457 exposed a pre-existing bug where non-JSON error responses
(like HTML 502 pages from load balancers) caused an unhelpful error:
"Invalid execution result: result is not object or array"

Changes:
- Modified parseResultFromResponse to safely attempt JSON parsing in
  the ELSE branch before failing
- Returns descriptive error messages for non-JSON responses
- Added comprehensive test coverage for HTML, plain text, and missing
  Content-Type scenarios
- Maintains backward compatibility for servers that omit Content-Type
  but still return valid JSON

The fix handles common production scenarios:
- Load balancer errors (502/503 with HTML)
- CDN errors (CloudFlare, Akamai)
- Misconfigured servers
- Rate limiters returning plain text
jasonkuhrt added a commit that referenced this pull request Nov 11, 2025
* Fix: handle non-JSON error responses gracefully

Fixes #1458

PR #1457 exposed a pre-existing bug where non-JSON error responses
(like HTML 502 pages from load balancers) caused an unhelpful error:
"Invalid execution result: result is not object or array"

Changes:
- Modified parseResultFromResponse to safely attempt JSON parsing in
  the ELSE branch before failing
- Returns descriptive error messages for non-JSON responses
- Added comprehensive test coverage for HTML, plain text, and missing
  Content-Type scenarios
- Maintains backward compatibility for servers that omit Content-Type
  but still return valid JSON

The fix handles common production scenarios:
- Load balancer errors (502/503 with HTML)
- CDN errors (CloudFlare, Akamai)
- Misconfigured servers
- Rate limiters returning plain text

* fix: format and lint issues

- Use backticks instead of single quotes for consistency
- Fix string concatenation formatting
- Break long test fixture line
jasonkuhrt added a commit that referenced this pull request Nov 17, 2025
This reverts:
- a9f94c1 chore: bump ver (7.3.3)
- 97d9822 Fix: handle non-JSON error responses gracefully (#1459)
- cc99d03 chore: bump version to 7.3.2
- 7a1ee76 fix: parse GraphQL errors from response body on HTTP 4xx/5xx status codes (#1457)

Reason: The approach of parsing body first then checking status led to cascading issues:
- #1461: ClientError replaced with generic Error for auth failures
- #1462: Unhelpful error messages for 401 responses

Will reimplement with a cleaner approach that:
- Returns ClientError for ALL non-2xx responses
- Preserves access to GraphQL errors in 4xx/5xx responses (#1281)
- Provides helpful error messages for parse failures
jasonkuhrt added a commit that referenced this pull request Nov 17, 2025
This reverts:
- a9f94c1 chore: bump ver (7.3.3)
- 97d9822 Fix: handle non-JSON error responses gracefully (#1459)
- cc99d03 chore: bump version to 7.3.2
- 7a1ee76 fix: parse GraphQL errors from response body on HTTP 4xx/5xx status codes (#1457)

Reason: The approach of parsing body first then checking status led to cascading issues:
- #1461: ClientError replaced with generic Error for auth failures
- #1462: Unhelpful error messages for 401 responses

Will reimplement with a cleaner approach that:
- Returns ClientError for ALL non-2xx responses
- Preserves access to GraphQL errors in 4xx/5xx responses (#1281)
- Provides helpful error messages for parse failures
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.

1 participant