arduino/Arduino · error · MaxRetryError

MaxRetryError(self, url, e)

Error message

MaxRetryError(self, url, e)

What it means

urllib3's HTTPConnectionPool.urlopen raises MaxRetryError(self, url, e) when retries is exhausted and the connection broke mid-request (HTTPException or SocketError after the request was sent). The MaxRetryError wraps the last underlying exception, so the retry budget was consumed by connection-level failures.

Source

Thrown at arduino-core/src/processing/app/i18n/python/requests/packages/urllib3/connectionpool.py:465

            raise TimeoutError(self, "Request timed out. (timeout=%s)" %
                               timeout)

        except BaseSSLError as e:
            # SSL certificate error
            raise SSLError(e)

        except CertificateError as e:
            # Name mismatch
            raise SSLError(e)

        except (HTTPException, SocketError) as e:
            # Connection broken, discard. It will be replaced next _get_conn().
            conn = None
            # This is necessary so we can access e below
            err = e

            if retries == 0:
                raise MaxRetryError(self, url, e)

        finally:
            if release_conn:
                # Put the connection back to be reused. If the connection is
                # expired then it will be None, which will get replaced with a
                # fresh connection during _get_conn.
                self._put_conn(conn)

        if not conn:
            # Try again
            log.warn("Retrying (%d attempts remain) after connection "
                     "broken by '%r': %s" % (retries, err, url))
            return self.urlopen(method, url, body, headers, retries - 1,
                                redirect, assert_same_host,
                                timeout=timeout, pool_timeout=pool_timeout,
                                release_conn=release_conn, **response_kw)

        # Handle redirect?

View on GitHub (pinned to a0df6e0e83)

Solutions

  1. Configure retries: urllib3.Retry(connect=3, read=3, backoff_factor=0.5) mounted on requests' HTTPAdapter
  2. Retry with idempotent requests, or disable urllib3 keep-alive (Connection: close header) to avoid stale-connection resets
  3. Check server/proxy health and network stability (the wrapped .reason exception tells the root cause)
  4. Increase retries for read errors if the endpoint is idempotent

Example fix

# before: single-shot, transient reset fails
requests.get('http://svc/api')
# after
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=Retry(total=3, backoff_factor=0.5)))
s.get('http://svc/api')
Defensive patterns

Strategy: retry

Validate before calling

from urllib3.util.retry import Retry
retry = Retry(total=3, connect=3, read=3, backoff_factor=0.5,
              status_forcelist=(500, 502, 503, 504))
# sanity check the endpoint before real traffic
requests.head(base_url, timeout=5)

Try / catch

from requests.exceptions import ConnectionError, MaxRetryError
try:
    r = session.get(url, timeout=10)
except (MaxRetryError, ConnectionError) as e:
    log.warning('connection retries exhausted: %s', getattr(e, 'reason', e))
    r = None  # fall back or alert

Prevention

When it happens

Trigger: Calling pool.urlopen(..., retries=0) or exhausting the default retry count while the socket dies (connection reset, remote close, keep-alive race), or any SocketError/HTTPException during the request when retries==0.

Common situations: Server closes idle keep-alive connections; flaky network or LB dropping connections; connecting to a service that is down or behind a rejecting proxy; retries=0 configured (e.g. by requests' HTTPAdapter defaults in old versions) so a single transient reset aborts.

Related errors


AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06). Data as JSON: /api/errors/02fc65bb3f32c698. Report an issue: GitHub.