gatsbyjs/gatsby · error · HttpError
response.statusText
Error message
response.statusText
What it means
Thrown by createGraphqlClient in gatsby-source-shopify when the Shopify Admin API responds with a non-ok status that is not retried (i.e. not a 5xx within the backoff window). The error message is response.statusText from node-fetch, and the full Response is attached as error.response for inspection. Common status codes: 401 (bad password/token), 403 (scope mismatch), 404 (wrong apiVersion/storeUrl), 429 (rate limit exceeded the backoff budget).
Source
Thrown at packages/gatsby-source-shopify/src/clients.ts:38
method: `POST`,
headers: {
"Content-Type": `application/json`,
"X-Shopify-Access-Token": options.password,
},
body: JSON.stringify({
query,
variables,
}),
})
if (!response.ok) {
const waitTime = 2 ** (retries + 1) + 500
if (response.status >= 500 && waitTime < MAX_BACKOFF_MILLISECONDS) {
await new Promise(resolve => setTimeout(resolve, waitTime))
return graphqlFetch(query, variables, retries + 1)
}
throw new HttpError(response)
}
const json = await response.json()
return json.data as T
}
return { request: graphqlFetch }
}
export function createRestClient(options: IShopifyPluginOptions): IRestClient {
const baseUrl = `https://${options.storeUrl}/admin/api/${options.apiVersion}`
async function shopifyFetch(
path: string,
fetchOptions = {
headers: {
"X-Shopify-Access-Token": options.password,
},View on GitHub (pinned to 8b06340921)
Solutions
- Inspect error.response.status and error.response.statusText to identify the failure class.
- For 401/403: regenerate the Shopify Admin API access token and verify the app's access scopes include the queried resources.
- For 404: confirm storeUrl (no protocol/scheme) and apiVersion (e.g. 2024-01) match a supported Shopify Admin API version.
- For 429: reduce parallelism or wait for the rate-limit window to reset; the plugin only retries 5xx, so throttle upstream.
Example fix
// before
resolve: `gatsby-source-shopify`,
options: { storeUrl: `https://mystore.myshopify.com`, password: process.env.SHOPIFY_KEY }
// after
resolve: `gatsby-source-shopify`,
options: { storeUrl: `mystore.myshopify.com`, password: process.env.SHOPIFY_ADMIN_TOKEN, apiVersion: `2024-01` } Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
function isHttpError(e): e is Error & { response: import('node-fetch').Response } { return e instanceof Error && 'response' in e && typeof (e as any).response?.status === 'number' } Try / catch
try { await client.request(query, variables) } catch (e) { if (isHttpError(e)) { if (e.response.status === 401) reporter.panic('Shopify token invalid/expired'); if (e.response.status === 404) reporter.panic('Shopify storeUrl or apiVersion wrong') } throw e } Prevention
- Store the Shopify Admin token in a secret manager and rotate it
- Verify storeUrl has no protocol/scheme and apiVersion is current
- Add a preflight GET to /admin/api/<version>/shop.json to validate credentials before sourcing
- Monitor 429s and throttle upstream to stay under Shopify rate limits
When it happens
Trigger: Wrong Shopify storeUrl or apiVersion producing 404; invalid or revoked access token producing 401; app uninstalled mid-build producing 403; rate-limit 429 that exceeded the MAX_BACKOFF_MILLISECONDS window; Shopify API version deprecated and removed.
Common situations: Token expired or app was uninstalled; apiVersion string mistyped or pinned to an old version that Shopify removed; storeUrl includes https:// or trailing slash; password field set to the API key instead of the secret; CI using a stale env var.
Related errors
- Source GraphQL API: HTTP error ${response.status} ${response
- Operation ${id} failed with ${errorCode}
- We had trouble connecting to Gatsby Cloud to create a login
- {"fetchError":"Could not fetch ${pathOrUrl} from official re
- Something went wrong when trying to add the plugins to the p
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/4ff54aef3eaeb1c6.
Report an issue: GitHub.