redis/redis-py · error · HttpError

HTTP {status} for {url}

Error message

HTTP {status} for {url}

What it means

Raised as redis.http.http_client.HttpError by HttpClient._json_call (redis/http/http_client.py:347) whenever an HTTP response has a status outside the 200–399 success range, after all configured retries are exhausted. The exception carries .status, .url, and the response body text so the caller can branch on the status code. RETRY_STATUS_CODES {429,500,502,503,504} are retried automatically before this is raised.

Source

Thrown at redis/http/http_client.py:347

        path: str,
        params: Optional[
            Mapping[str, Union[None, str, int, float, bool, list, tuple]]
        ] = None,
        headers: Optional[Mapping[str, str]] = None,
        timeout: Optional[float] = None,
        body: Optional[Union[bytes, str]] = None,
        expect_json: bool = True,
    ) -> Union[HttpResponse, Any]:
        resp = self.request(
            method=method,
            path=path,
            params=params,
            headers=headers,
            body=body,
            timeout=timeout,
        )
        if not (200 <= resp.status < 400):
            raise HttpError(resp.status, resp.url, resp.text())
        if expect_json:
            return resp.json()
        return resp

    def _prepare_body(
        self, json_body: Optional[Any] = None, data: Optional[Union[bytes, str]] = None
    ) -> Optional[Union[bytes, str]]:
        if json_body is not None and data is not None:
            raise ValueError("Provide either json_body or data, not both.")
        if json_body is not None:
            return json.dumps(json_body, ensure_ascii=False, separators=(",", ":"))
        return data

    def _build_url(
        self,
        path: str,
        params: Optional[
            Mapping[str, Union[None, str, int, float, bool, list, tuple]]

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Catch HttpError and branch on exc.status: refresh credentials on 401, fix the path on 404, surface 4xx as caller errors.
  2. For 5xx, increase Retry.retries / widen _should_retry_status or retry at the call site with backoff.
  3. Log exc.url and exc.message (and exc.text via resp) to pinpoint the failing endpoint.
  4. Verify auth headers, base_url, and mTLS cert/key paths are correct for the target service.

Example fix

// before
resp = client.post('/v1/token', json_body=payload)  # HttpError on 4xx/5xx

// after
from redis.http.http_client import HttpError
try:
    resp = client.post('/v1/token', json_body=payload)
except HttpError as e:
    if e.status in (401, 403):
        refresh_credentials()
        raise
    raise
Defensive patterns

Strategy: try-catch

Type guard

from redis.http.http_client import HttpError
def is_http_error(e) -> bool:
    return isinstance(e, HttpError)

Try / catch

from redis.http.http_client import HttpError
try:
    resp = client.post('/v1/token', json_body=payload)
except HttpError as e:
    if e.status in (401, 403):
        refresh_credentials()  # then optionally retry
    if 500 <= e.status < 600 and e.status in {500, 502, 503, 504}:
        # already retried by client; surface as transient
        raise TransientUpstream(e)
    raise

Prevention

When it happens

Trigger: Any HttpClient .get/.post/.put/.patch/.delete (or _json_call) call whose final response status is >= 400: 401/403 auth failure, 404 not found, 400 bad request, or a non-retryable 5xx after retries give up.

Common situations: Expired/invalid auth token (401/403); wrong endpoint or path (404); malformed request body (400); upstream outage returning a non-retryable error; TLS/mTLS misconfiguration surfacing as a 4xx from a gateway.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/985433b5d3330969.json. Report an issue: GitHub.