pypa/pip · error · ConnectionTimeoutError

connection-timeout

connection-timeout

Error message

Unable to fetch {url}

What it means

Raised as ConnectionTimeoutError (kind='connect') from _raise_timeout_error when urllib3 reports a ConnectTimeoutError: the TCP connection to the host did not complete within the configured connect timeout. The user-facing message is 'Unable to fetch {url}'.

Solutions

  1. Raise the timeout: pip install --timeout 60 <pkg>.
  2. Verify the host is reachable (curl, ping) and DNS resolves correctly.
  3. Check firewall/proxy rules that may be dropping outbound HTTPS.
  4. Retry; transient connect timeouts often succeed on a second attempt.

Example fix

# before
pip install pkg

# after
pip install --timeout 60 pkg
Defensive patterns

Strategy: retry

Validate before calling

import socket

def host_connects(host: str, port: int = 443, timeout: float = 5.0) -> bool:
    try:
        with socket.create_connection((host, port), timeout=timeout):
            return True
    except OSError:
        return False

Try / catch

from pip._internal.exceptions import ConnectionTimeoutError

try:
    run_pip_install(["--timeout", "60", "pkg"])
except ConnectionTimeoutError:
    run_pip_install(["--timeout", "120", "pkg"])

Prevention

When it happens

Trigger: Pip requests a URL and the TCP handshake to the resolved host does not finish in time (SYN sent but no SYN-ACK, or host unreachable), causing urllib3.exceptions.ConnectTimeoutError to surface through raise_connection_error.

Common situations: Offline or captive-portal networks; very slow corporate links; firewall silently dropping packets; DNS resolves to a non-routable IP; default 15s timeout too short for a slow link.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/195cd038c5e86651. Report an issue: GitHub.

Appendix: source

Thrown at src/pip/_internal/network/utils.py:145

    else:
        connect_timeout = read_timeout = timeout

    if kind == "connect":
        assert connect_timeout is not None
        return connect_timeout
    else:
        assert read_timeout is not None
        return read_timeout


def _raise_timeout_error(
    reason: urllib3.exceptions.TimeoutError,
    url: str,
    host: str,
    timeout: TimeoutValue,
) -> NoReturn:
    if isinstance(reason, urllib3.exceptions.ConnectTimeoutError):
        raise ConnectionTimeoutError(
            url, host, kind="connect", timeout=_parse_timeout(timeout, "connect")
        )
    else:
        raise ConnectionTimeoutError(
            url, host, kind="read", timeout=_parse_timeout(timeout, "read")
        )


def raise_connection_error(
    error: requests.ConnectionError | requests.Timeout,
    *,
    url: str,
    timeout: TimeoutValue,
) -> NoReturn:
    """Raise a specific error for a given connection error, if possible.

    Note: requests.ConnectionError is the parent class of
          requests.ProxyError, requests.SSLError, and requests.ConnectTimeout

View on GitHub (pinned to f399c37189)