{"record":{"id":"2ce6e894a87a648d","repo":"redis/node-redis","slug":"http-response-status-unable-to-parse-response","errorCode":null,"errorMessage":"HTTP ${response.status} - Unable to parse response as JSON","messagePattern":"HTTP (.+?) - Unable to parse response as JSON","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/test-utils/lib/fault-injector/fault-injector-client.ts","lineNumber":234,"sourceCode":"        headers,\n        body: payload,\n        signal: controller.signal\n      });\n\n      if (!response.ok) {\n        try {\n          const text = await response.text();\n          throw new Error(`HTTP ${response.status} - ${text}`);\n        } catch {\n          throw new Error(`HTTP ${response.status}`);\n        }\n      }\n\n      try {\n        const result = (await response.json()) as T;\n        return result;\n      } catch {\n        throw new Error(\n          `HTTP ${response.status} - Unable to parse response as JSON`\n        );\n      }\n    } finally {\n      globalThis.clearTimeout(timeoutId);\n    }\n  }\n\n  /**\n   * Deletes a database.\n   * @param clusterIndex The index of the cluster\n   * @param bdbId The database ID (optional if dbConfig is set)\n   * @throws {Error} When the HTTP request fails or response cannot be parsed as JSON\n   */\n  public async deleteDatabase(\n    bdbId?: number | string,\n    clusterIndex: number = 0\n  ) {","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/test-utils/lib/fault-injector/fault-injector-client.ts#L216-L252","documentation":"Thrown by #request when response.ok is true (2xx) but response.json() throws — the server returned a 2xx with a body that is not valid JSON. The status code is included so the caller can see the successful HTTP status that preceded the parse failure.","triggerScenarios":"The fault-injector endpoint returns 200 with an empty body, an HTML error page, or plain text instead of JSON; a proxy/gateway in front rewrites the response; the endpoint changed its content type.","commonSituations":"Reverse proxy returning an HTML 200 error page; misconfigured baseUrl pointing at a non-API server; service version mismatch where an endpoint now returns text; truncated response on a flaky connection.","solutions":["Reproduce the request with curl -i to inspect Content-Type and the raw body","Confirm baseUrl points at the fault-injector API, not a generic web server","Verify the fault-injector service version matches the client's expected contract"],"exampleFix":"# before\nError: HTTP 200 - Unable to parse response as JSON\n\n# after — inspect the actual response\ncurl -i $FI_BASE_URL/action\n# if it returns HTML, fix baseUrl to the real API host","handlingStrategy":"validation","validationCode":"async function safeRequest<T>(fi: FaultInjectorClient, method: string, path: string): Promise<T> {\n  try {\n    return await (fi as any).#request<T>(method, path);\n  } catch (e) {\n    if (e instanceof Error && /Unable to parse response as JSON/.test(e.message)) {\n      throw new Error(`${e.message} — check that baseUrl points at the JSON API`);\n    }\n    throw e;\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fi.listActions();\n} catch (e) {\n  if (e instanceof Error && /Unable to parse response as JSON/.test(e.message)) {\n  }\n  throw e;\n}","preventionTips":["Verify baseUrl points at the JSON API, not a web server returning HTML","Reproduce the request with curl -i to inspect Content-Type","Ensure the fault-injector service version matches the client's expected JSON contract"],"tags":["fault-injection","http","json","test-utils","parsing"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}