{"record":{"id":"e5f1ca20c4fc8508","repo":"psf/requests","slug":"err","errorCode":null,"errorMessage":"{err}","messagePattern":"\\{err\\}","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"src/requests/adapters.py","lineNumber":711,"sourceCode":"            resolved_timeout = TimeoutSauce(connect=timeout, read=timeout)\n\n        try:\n            resp = conn.urlopen(\n                method=request.method,\n                url=url,\n                body=request.body,  # type: ignore[arg-type]  # urllib3 stubs don't accept Iterable[bytes | str]\n                headers=request.headers,  # type: ignore[arg-type]  # urllib3#3072\n                redirect=False,\n                assert_same_host=False,\n                preload_content=False,\n                decode_content=False,\n                retries=self.max_retries,\n                timeout=resolved_timeout,\n                chunked=chunked,\n            )\n\n        except (ProtocolError, OSError) as err:\n            raise ConnectionError(err, request=request)\n\n        except MaxRetryError as e:\n            if isinstance(e.reason, ConnectTimeoutError):\n                # TODO: Remove this in 3.0.0: see #2811\n                if not isinstance(e.reason, NewConnectionError):\n                    raise ConnectTimeout(e, request=request)\n\n            if isinstance(e.reason, ResponseError):\n                raise RetryError(e, request=request)\n\n            if isinstance(e.reason, _ProxyError):\n                raise ProxyError(e, request=request)\n\n            if isinstance(e.reason, _SSLError):\n                # This branch is for urllib3 v1.22 and later.\n                raise SSLError(e, request=request)\n\n            raise ConnectionError(e, request=request)","sourceCodeStart":693,"sourceCodeEnd":729,"githubUrl":"https://github.com/psf/requests/blob/8068356288978c4f54661ae6f95afe0e0831885e/src/requests/adapters.py#L693-L729","documentation":"This is the catch-all mapping of low-level transport errors to requests' ConnectionError. When conn.urlopen raises a urllib3 ProtocolError or a builtin OSError (e.g. socket-level ECONNREFUSED, EAI_AGAIN DNS failure, broken pipe), the adapter wraps it as ConnectionError(err, request=request). It indicates the request never produced a usable response due to a network/transport failure.","triggerScenarios":"Triggered by any OSError or urllib3.exceptions.ProtocolError during the urlopen call: DNS resolution failure, connection refused, network unreachable, TCP reset, broken pipe, or a proxy protocol violation. Fires after the connection is obtained and the request is dispatched.","commonSituations":"Seen during transient network blips, when the target host is down or DNS is flaky, when a firewall drops the connection, when a proxy returns malformed responses, or in containers with misconfigured DNS (e.g. resolving an internal host that is not resolvable).","solutions":["Retry with backoff for transient errors (ConnectionError often resolves on retry); use urllib3 Retry or tenacity.","Verify the host resolves and is reachable (socket.getaddrinfo, a manual curl) to distinguish DNS from firewall issues.","Check proxy configuration if the failure mentions a proxy.","Increase the connect timeout if the error is timeout-adjacent; capture e.args for the underlying errno.","For production, wrap requests calls in a retry decorator that targets ConnectionError and ReadTimeout."],"exampleFix":"# before\nresp = requests.get(url)  # intermittent ConnectionError\n\n# after\nimport requests\nfrom requests.adapters import HTTPAdapter\nfrom urllib3.util.retry import Retry\n\ns = requests.Session()\nretry = Retry(total=3, backoff_factor=0.3,\n              status_forcelist=[502, 503, 504])\ns.mount(\"https://\", HTTPAdapter(max_retries=retry))\nresp = s.get(url)","handlingStrategy":"retry","validationCode":"import socket\n\ndef preflight_host(url: str, timeout: float = 5.0) -> None:\n    \"\"\"Resolve + TCP-connect to the host to fail fast on DNS/firewall issues.\"\"\"\n    from urllib.parse import urlparse\n    p = urlparse(url)\n    host = p.hostname\n    port = p.port or (443 if p.scheme == \"https\" else 80)\n    try:\n        socket.getaddrinfo(host, port, type=socket.SOCK_STREAM)\n    except socket.gaierror as e:\n        raise ConnectionError(f\"DNS resolution failed for {host}: {e}\") from e\n\npreflight_host(url)","typeGuard":"# ConnectionError is a runtime/network failure; the relevant guard is a\n# reachability check rather than a type narrowing.\ndef is_host_reachable(host: str, port: int, timeout: float = 3.0) -> bool:\n    import socket\n    try:\n        with socket.create_connection((host, port), timeout=timeout):\n            return True\n    except OSError:\n        return False","tryCatchPattern":"import time\nimport requests.exceptions as exc\n\ndef get_with_retry(session, url, attempts=3, backoff=0.5):\n    last = None\n    for i in range(attempts):\n        try:\n            return session.get(url)\n        except exc.ConnectionError as e:\n            last = e\n            time.sleep(backoff * (2 ** i))\n    raise last","preventionTips":["Mount an HTTPAdapter with a Retry policy for transient ConnectionError.\nDistinguish DNS errors from firewall errors with a preflight reachability check.\nLog e.args to capture the underlying errno/socket error.\nIn containers, verify DNS config (/etc/resolv.conf) and proxy settings."],"tags":["network","connection-error","protocol-error","retry"],"backgroundTag":null,"analyzedSha":"8068356288978c4f54661ae6f95afe0e0831885e","analyzedAt":"2026-08-11T20:11:09.238Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}