psf/requests · error · HTTPError

{self.status_code} Server Error: {reason} for url: {self.url

Error message

{self.status_code} Server Error: {reason} for url: {self.url}

What it means

Raised by Response.raise_for_status() in src/requests/models.py when the response status code is in the 5xx range (500 <= status_code < 600). It signals that the server (or an intermediary such as a load balancer or proxy) failed to fulfill a request that may itself have been valid; Requests surfaces it as requests.exceptions.HTTPError with the status, reason, and final URL.

Source

Thrown at src/requests/models.py:1171

            try:
                reason = self.reason.decode("utf-8")
            except UnicodeDecodeError:
                reason = self.reason.decode("iso-8859-1")
        else:
            reason = self.reason

        if 400 <= self.status_code < 500:
            http_error_msg = (
                f"{self.status_code} Client Error: {reason} for url: {self.url}"
            )

        elif 500 <= self.status_code < 600:
            http_error_msg = (
                f"{self.status_code} Server Error: {reason} for url: {self.url}"
            )

        if http_error_msg:
            raise HTTPError(http_error_msg, response=self)

    def close(self) -> None:
        """Releases the connection back to the pool. Once this method has been
        called the underlying ``raw`` object must not be accessed again.

        *Note: Should not normally need to be called explicitly.*
        """
        if not self._content_consumed:
            self.raw.close()

        release_conn = getattr(self.raw, "release_conn", None)
        if release_conn is not None:
            release_conn()

View on GitHub ↗ (pinned to 414f0513c3)

Solutions

  1. Retry with exponential backoff for transient 5xx: mount an HTTPAdapter with urllib3.util.Retry(total=3, backoff_factor=1, status_forcelist=[500,502,503,504]).
  2. Log response.text — many servers include a request ID or stack trace fragment useful for reporting the issue upstream.
  3. If a specific payload reliably triggers 500, minimize and report it to the API owner; validate your input format against the API docs.
  4. Check service status pages / health endpoints before assuming a client-side bug.

Example fix

# before
resp = requests.get(url)
resp.raise_for_status()

# after
from requests.adapters import HTTPAdapter
from urllib3.util import Retry

session = requests.Session()
retry = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
session.mount("https://", HTTPAdapter(max_retries=retry))
resp = session.get(url)
resp.raise_for_status()
Defensive patterns

Strategy: retry

Type guard

def is_server_error(resp):
    return 500 <= resp.status_code < 600

Try / catch

try:
    resp = session.get(url, timeout=10)
    resp.raise_for_status()
except requests.exceptions.HTTPError as e:
    if e.response is not None and e.response.status_code >= 500:
        retry_with_backoff()

Prevention

When it happens

Trigger: Calling response.raise_for_status() when the server returned 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, or 504 Gateway Timeout — e.g. hitting an API during a deploy, an upstream backend being down behind a reverse proxy, or a request payload that crashes the server-side handler.

Common situations: Transient outages and deploy windows (502/503), overloaded services shedding load (503), gateway timeouts on slow upstream calls (504), and genuine server bugs triggered by specific inputs (500). CI pipelines and cron jobs commonly hit these intermittently.

Related errors


AI-assisted analysis of psf/requests@414f0513c3 (2026-07-31). Data as JSON: /data/errors/a576b541fa19c3c5.json. Report an issue: GitHub ↗.