Skip to content

Treat HTTP 520 to 524 from the Admin API as gateway errors - #9042

Open
isaacroldan wants to merge 2 commits into
mainfrom
torrent/cli-4-treat-http-520-to-524-from-theme-admin-a
Open

isaacroldan wants to merge 2 commits into
mainfrom
torrent/cli-4-treat-http-520-to-524-from-theme-admin-a

Conversation

@isaacroldan

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

Theme Admin API reads use handleErrors: false. So a raw ClientError from graphql-request reaches shouldReportErrorAsUnexpected. When the Cloudflare edge in front of the API answers HTTP 520 to 524, the body is an HTML error page ("Something went wrong"), not JSON. isExpectedApiError accepts only 401, 429, 502, 503 and 504. So the CLI reports this infrastructure failure as an unexpected error, as if it were a CLI bug.

WHAT is this pull request doing?

  • Adds 520, 521, 522, 523 and 524 to GATEWAY_ERROR_STATUSES in packages/cli-kit/src/private/node/api/status-checks.ts. HTTP 500 stays out, because it can come from a real server bug.
  • isExpectedApiError now treats a raw ClientError with these statuses as an expected gateway error.
  • The device authorization flow uses the same helper. It now also retries these statuses, and reports them as an AbortError, the same as 502, 503 and 504.
  • Adds regression tests in error/index.test.ts (520 to 524 are expected, 500 is still unexpected) and themes/api.test.ts (fetchThemes that gets a 520 HTML response throws an error that is not reported as unexpected).

How to manually test your changes?

  1. Check out this branch and run pnpm install.
  2. Save this as packages/cli-kit/check-gateway.ts:
    import {ClientError} from 'graphql-request'
    import {shouldReportErrorAsUnexpected} from './src/public/node/error.js'
    for (const status of [500, 502, 520, 524]) {
      const error = new ClientError({status, headers: {}, error: '<html></html>'} as never, {query: ''})
      console.log(status, shouldReportErrorAsUnexpected(error))
    }
  3. Run pnpm tsx check-gateway.ts in packages/cli-kit.
  4. Expect 500 true, 502 false, 520 false, 524 false. On main, 520 and 524 print true.
  5. Delete the file.

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes
  • I've considered analytics changes to measure impact
  • The change is user-facing — I've identified the correct bump type (patch for bug fixes · minor for new features · major for breaking changes) and added a changeset with pnpm changeset add

@github-actions github-actions Bot added the Area: @shopify/cli @shopify/cli package issues label Oct 29, 2026
@isaacroldan
isaacroldan marked this pull request as ready for review October 29, 2026 12:54
@isaacroldan
isaacroldan requested review from a team as code owners October 29, 2026 12:54

@alexanderMontague alexanderMontague left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Both consumers of isGatewayErrorStatus are accounted for and the change makes sense in each:

  • isExpectedApiError — raw ClientErrors with 520–524 stop being reported as unexpected. This only matters on the handleErrors: false path (theme reads); the default path already wraps 5xx into an AbortError in errorHandler, so no inconsistency is introduced.
  • device-authorization.ts — now also retries 520–524 and throws AbortError instead of BugError on an unparseable body. The POST to /oauth/device_authorization just mints a new device code, so retrying is safe.

Two non-blocking points:

Question: why stop at 524? Cloudflare also returns 525/526 (origin TLS failures) and 530. Those are also HTML edge pages that would still be reported as unexpected. Excluding them from retry makes sense (they're not transient), but if the goal is "don't blame the CLI for edge errors", you may want them in isExpectedApiError too. Fine to leave as-is if you'd rather keep one list.

Nit: the themes/api.test.ts test mocks adminRequestDoc to reject, so "when the edge answers HTTP 520" isn't really what's exercised — it proves requestThemeAdminDoc rethrows the ClientError unchanged and then re-asserts the unit test. Still a reasonable thing to lock down, but the name overstates it.


Generated with Pi. Vetted by Me.

@isaacroldan
isaacroldan enabled auto-merge November 5, 2026 14:13
Theme Admin API reads use handleErrors: false, so a raw ClientError
reaches shouldReportErrorAsUnexpected. When the Cloudflare edge answers
520 to 524 with an HTML error page, isExpectedApiError did not match it
and the CLI reported an infrastructure failure as an unexpected error.

Add 520 to 524 to the gateway statuses in status-checks.ts. 500 stays
out, because it can be a real server bug. The device authorization flow
uses the same helper, so it now also retries these statuses.

Co-authored-by: isaac.roldan <isaac.roldan@shopify.com>
@isaacroldan
isaacroldan force-pushed the torrent/cli-4-treat-http-520-to-524-from-theme-admin-a branch from 4763b40 to bccd823 Compare November 5, 2026 14:23
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

We found no new type declarations in this PR

Existing type declarations

packages/cli-kit/dist/private/node/api/status-checks.d.ts
@@ -2,6 +2,6 @@
  * Checks whether an HTTP status indicates a gateway-level failure.
  *
  * @param status - The HTTP status to check.
- * @returns Whether the status is 502, 503, or 504.
+ * @returns Whether the status is 502, 503, 504, or a Cloudflare edge error from 520 to 524.
  */
 export declare function isGatewayErrorStatus(status: number | undefined): boolean;
\ No newline at end of file

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

Area: @shopify/cli @shopify/cli package issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants