{"record":{"id":"ded2301f73c2595f","repo":"Budibase/budibase","slug":"failed-to-parse-response-body-err","errorCode":null,"errorMessage":"Failed to parse response body: ${err}","messagePattern":"Failed to parse response body: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/server/src/integrations/rest.ts","lineNumber":336,"sourceCode":"        } else if (\n          (hasContent && contentType.includes(\"text/xml\")) ||\n          contentType.includes(\"application/xml\")\n        ) {\n          triedParsing = true\n          let xmlResponse = await handleXml(responseTxt)\n          data = xmlResponse.data as JSONValue\n          raw = xmlResponse.rawXml\n        } else {\n          data = responseTxt\n          raw = responseTxt\n        }\n      }\n    } catch (err) {\n      if (triedParsing) {\n        data = responseTxt\n        raw = responseTxt\n      } else {\n        throw new Error(`Failed to parse response body: ${err}`)\n      }\n    }\n\n    const size = helpers.formatBytes(contentLength || \"0\")\n    const time = `${Math.round(performance.now() - this.startTimeMs)}ms`\n    // converts headers to plain object\n    for (const [key, value] of response.headers.entries()) {\n      headers[key] = value\n    }\n\n    // Check if a pagination cursor exists in the response\n    let nextCursor: JSONValue | undefined\n    if (pagination?.responseParam) {\n      nextCursor = get(data, pagination.responseParam) as JSONValue | undefined\n    }\n\n    return {\n      data,","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/integrations/rest.ts#L318-L354","documentation":"parseResponse attempts to parse the HTTP response body as JSON or XML based on the Content-Type header. If parsing throws and nothing had actually started parsing (triedParsing false), it rethrows as 'Failed to parse response body: <cause>'. This guards queries against bodies that claim a structured content type but are malformed or not parseable.","triggerScenarios":"A REST query whose response Content-Type is application/json (or xml) but whose body is invalid JSON/XML - e.g. an HTML error page or truncated body served with a JSON content-type header. Also thrown when reading response.text() itself fails before any parse attempt.","commonSituations":"API gateway/WAF returns an HTML 502/error page with Content-Type: application/json; response truncated mid-body; BOM or leading whitespace mixed with valid content in edge cases; upstream returns JSONP or single-quoted JSON mislabeled as application/json.","solutions":["Inspect the raw response body and its Content-Type header; fix the upstream to return valid content for the declared type","If the endpoint returns HTML errors, fix auth/URL or handle the non-2xx status before parsing","Point the query at an endpoint that returns well-formed JSON, or accept the plain-text fallback (bodies with non-JSON content types are returned as text)","If the upstream truly mislabels content type, use a proxy/transform to correct the header or parse client-side","Add retry logic for truncated responses from flaky upstreams"],"exampleFix":"// before: upstream returns HTML with Content-Type: application/json\nContent-Type: application/json\n<html>502 Bad Gateway</html>\n// after: ensure upstream or proxy returns valid body for the type\nContent-Type: application/json\n{\"ok\": true}","handlingStrategy":"validation","validationCode":"// validate body parses before handing to the query runner\nconst res = await fetch(url, opts)\nconst ct = res.headers.get(\"content-type\") || \"\"\nif (ct.includes(\"application/json\")) {\n  try { JSON.parse(await res.text()) } catch {\n    throw new Error(\"Upstream returned non-JSON body with JSON content-type\")\n  }\n}","typeGuard":"function isParseableJson(txt) {\n  if (typeof txt !== \"string\") return false\n  try { JSON.parse(txt); return true } catch { return false }\n}","tryCatchPattern":"try {\n  const result = await restQuery.execute()\n} catch (e) {\n  if (String(e.message).startsWith(\"Failed to parse response body:\")) {\n    // inspect raw body/status manually; treat as upstream content bug\n  } else { throw e }\n}","preventionTips":["Verify endpoints return valid JSON with a matching Content-Type header","Handle non-2xx responses before parsing - gateways often return HTML error pages","Use relative paths/correct auth so you hit the real API, not an error interstitial","For flaky upstreams, retry truncated responses"],"tags":["http","rest","json","parsing"],"backgroundTag":"invalid-json-response","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}