{"record":{"id":"529ec8a2fb117683","repo":"redis/redis-py","slug":"response-body","errorCode":null,"errorMessage":"{response_body}","messagePattern":"\\{response_body\\}","errorType":"http","errorClass":"HttpError","httpStatus":null,"severity":"error","filePath":"redis/http/http_client.py","lineNumber":347,"sourceCode":"        path: str,\n        params: Optional[\n            Mapping[str, Union[None, str, int, float, bool, list, tuple]]\n        ] = None,\n        headers: Optional[Mapping[str, str]] = None,\n        timeout: Optional[float] = None,\n        body: Optional[Union[bytes, str]] = None,\n        expect_json: bool = True,\n    ) -> Union[HttpResponse, Any]:\n        resp = self.request(\n            method=method,\n            path=path,\n            params=params,\n            headers=headers,\n            body=body,\n            timeout=timeout,\n        )\n        if not (200 <= resp.status < 400):\n            raise HttpError(resp.status, resp.url, resp.text())\n        if expect_json:\n            return resp.json()\n        return resp\n\n    def _prepare_body(\n        self, json_body: Optional[Any] = None, data: Optional[Union[bytes, str]] = None\n    ) -> Optional[Union[bytes, str]]:\n        if json_body is not None and data is not None:\n            raise ValueError(\"Provide either json_body or data, not both.\")\n        if json_body is not None:\n            return json.dumps(json_body, ensure_ascii=False, separators=(\",\", \":\"))\n        return data\n\n    def _build_url(\n        self,\n        path: str,\n        params: Optional[\n            Mapping[str, Union[None, str, int, float, bool, list, tuple]]","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/http/http_client.py#L329-L365","documentation":"_json_call (redis/http/http_client.py:347) raises HttpError(resp.status, resp.url, resp.text()) whenever the HTTP response status is outside the 200-399 success range. The exception's message is the raw response body text ({response_body}), and HttpError also exposes .status and .url for programmatic handling. This is the HttpClient's single failure path for non-success HTTP responses used by auth/scenario HTTP flows.","triggerScenarios":"Any HttpClient.get/post/put/patch/delete/request that returns 4xx or 5xx (and is not retried away): 401/403 from an auth endpoint when the token is expired/invalid, 404 from a wrong path, 400 from a malformed JSON body, 5xx from an upstream outage after retries are exhausted.","commonSituations":"Expired OAuth/EntraID token hitting the token endpoint; wrong base_url/path; sending json_body that fails server validation; the token-issuer or scenario-test service being down; rate limiting (429) after the retry budget is spent.","solutions":["Inspect err.status to branch: refresh credentials on 401/403, fix the URL/body on 4xx, retry/backoff on 5xx/429.","Increase the retry count / backoff (Retry with ExponentialWithJitterBackoff) so transient 429/5xx are absorbed before surfacing.","Verify base_url, path, and required headers (Authorization, Content-Type) match the service contract.","Log err.url and err.status (not the full body if it may contain secrets) for diagnosis."],"exampleFix":"// before\nresp = http.post('/v1/token', json_body=payload)\n// after\nfrom redis.http.http_client import HttpError\ntry:\n    resp = http.post('/v1/token', json_body=payload)\nexcept HttpError as e:\n    if e.status in (401, 403):\n        refresh_token(); resp = http.post('/v1/token', json_body=payload)\n    else:\n        raise","handlingStrategy":"try-catch","validationCode":"def is_likely_ok(method: str, path: str, body) -> bool:\n    # cheap client-side sanity before the call\n    return bool(path) and (body is None or isinstance(body, (dict, bytes, str)))","typeGuard":"from redis.http.http_client import HttpError\ndef is_http_error(e) -> bool:\n    return isinstance(e, HttpError)","tryCatchPattern":"from redis.http.http_client import HttpError\ntry:\n    resp = http.post('/v1/token', json_body=payload)\nexcept HttpError as e:\n    if e.status in (401, 403):\n        refresh_credentials()\n        resp = http.post('/v1/token', json_body=payload)\n    elif e.status >= 500:\n        raise  # or retry with backoff\n    else:\n        raise","preventionTips":["Branch on err.status: refresh creds on 401/403, fix request on 4xx, retry on 5xx/429.","Verify base_url, path, and headers match the service contract before relying on retries.","Tune the HttpClient retry/backoff so transient 429/5xx are absorbed.","Log err.status and err.url; avoid dumping the body if it may contain secrets."],"tags":["http","http-error","api","auth"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}