{"record":{"id":"cebe6b7c06b1f9fd","repo":"gatsbyjs/gatsby","slug":"source-graphql-api-http-error-response-status","errorCode":null,"errorMessage":"Source GraphQL API: HTTP error ${response.status} ${response.statusText}","messagePattern":"Source GraphQL API: HTTP error (.+?) (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/gatsby-source-graphql/src/fetch.js","lineNumber":10,"sourceCode":"const nodeFetch = require(`node-fetch`).default\n\n// this is passed to the Apollo Link\n// https://www.apollographql.com/docs/link/links/http/#fetch-polyfill\n\nexports.fetchWrapper = async (uri, options) => {\n  const response = await nodeFetch(uri, options)\n\n  if (response.status >= 400) {\n    throw new Error(\n      `Source GraphQL API: HTTP error ${response.status} ${response.statusText}`\n    )\n  }\n\n  return response\n}\n","sourceCodeStart":1,"sourceCodeEnd":17,"githubUrl":"https://github.com/gatsbyjs/gatsby/blob/8b06340921ffdf23125a365b9c9923690cb62ce6/packages/gatsby-source-graphql/src/fetch.js#L1-L17","documentation":"gatsby-source-graphql wraps every outbound GraphQL fetch in node-fetch and throws when the HTTP response status is 400 or above. The message surfaces status code and statusText from the remote server so the user can see whether it is an auth failure (401/403), a client error (400), or a server error (5xx). The error is thrown from the Apollo Link fetch polyfill, so it propagates through the Apollo client into the sourcing pipeline.","triggerScenarios":"Remote GraphQL endpoint returns 401/403 (bad or expired token); 404 from a wrong URL; 400 from a malformed query body; 5xx from upstream outage; CORS/network proxy returning a 502; rate-limited endpoint returning 429.","commonSituations":"Typo in the GraphQL endpoint url; expired API key or missing Authorization header; remote schema changed and queries now reference removed fields; environment variable holding the token not set in CI; reverse proxy in front of the GraphQL API returning HTML error pages.","solutions":["Verify the url in plugin options resolves to the GraphQL endpoint (curl -i with the same headers).","Confirm authentication headers (Authorization, custom tokens) are present and valid in the current environment.","Check the remote server health — a 5xx is upstream; retry later or contact the API provider.","If a 400, run the failing query against the endpoint directly to see the GraphQL error details."],"exampleFix":"// before\nresolve: `gatsby-source-graphql`,\noptions: { url: `https://api.example.com/graphql` }\n\n// after\nresolve: `gatsby-source-graphql`,\noptions: {\n  url: `https://api.example.com/graphql`,\n  headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try { await apolloClient.query({ query }) } catch (e) { if (/Source GraphQL API: HTTP error/.test(e.message)) { const code = e.message.match(/HTTP error (\\d+)/)?.[1]; reporter.panic(`Remote GraphQL endpoint returned ${code}; check url and auth`) } throw e }","preventionTips":["Smoke-test the GraphQL endpoint with curl using the same headers before running the build","Keep the API token in a managed secret, not in plaintext config","Add health-check polling before the build to catch upstream outages","Pin the remote schema version when possible to avoid mid-stream breakage"],"tags":["gatsby","graphql","network","http","auth"],"backgroundTag":null,"analyzedSha":"8b06340921ffdf23125a365b9c9923690cb62ce6","analyzedAt":"2026-08-13T02:36:21.405Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}