Skip to content

[BUG] httpx.Client() crashes when NO_PROXY contains bracketed IPv6 [::1] — Invalid port ':1]' #1541

Description

@FiretrUCK666

Bug Description

Constructing a default httpx.Client() (with trust_env=True) crashes at startup when the process environment contains a bracketed IPv6 loopback in NO_PROXY / no_proxy, e.g. localhost,127.0.0.1,::1,[::1]. The [::1] entry is treated as a URL, its :1] suffix is parsed as a port, and client construction raises instead of starting.

This bit us in the field: an MCP host process inherited that NO_PROXY value, so every httpx.Client() created by Basic Memory's dependency tree blew up with Invalid port: ':1]' (same signature as the FastEmbed Invalid port failure). Removing just the [::1] entry (keeping bare ::1) fixes it.

Steps To Reproduce

  1. Install version 0.23.2 (bundles httpx 0.28.1).
  2. Set the environment (Windows 11, but the parsing bug is platform-independent):
    • NO_PROXY=localhost,127.0.0.1,::1,[::1]
    • no_proxy=localhost,127.0.0.1,::1,[::1]
  3. Run:
    import httpx
    c = httpx.Client()
  4. See error (reproduced with the venv interpreter shipped by uvx --prerelease=allow basic-memory mcp).

Control case: scrubbing the env in-process to NO_PROXY=localhost,127.0.0.1,::1 (bare IPv6, no brackets) plus HTTP_PROXY/HTTPS_PROXY/ALL_PROXY=http://127.0.0.1:7078 constructs the client fine.

Expected Behavior

A bracketed IPv6 loopback in NO_PROXY should be accepted (it is the standard URL-form of ::1, and tools like curl accept it), or at worst that single entry should be skipped with a warning. Client construction must not raise for a bypass-list entry.

Actual Behavior

httpx.Client() raises during __init__:

ValueError: invalid literal for int() with base 10: ':1]'
...
  File "httpx/_client.py", line 698, in __init__
    URLPattern(key): None
  File "httpx/_utils.py", line 172, in __init__
    url = URL(pattern)
  File "httpx/_urls.py", line 117, in __init__
    self._uri_reference = urlparse(url, **kwargs)
  File "httpx/_urlparse.py", line 321, in urlparse
    parsed_port: int | None = normalize_port(port, scheme)
  File "httpx/_urlparse.py", line 411, in normalize_port
    raise InvalidURL(f"Invalid port: {port!r}")
httpx.InvalidURL: Invalid port: ':1]'

So any code path that builds a default client while that NO_PROXY value is present fails before doing any work.

Environment

  • OS: Windows 11 (10.0.26200)
  • Python version: 3.12.12 (venv created by uv)
  • Basic Memory version: 0.23.2
  • Installation method: uvx --prerelease=allow basic-memory mcp (uvx 0.11.3)
  • Bundled httpx version: 0.28.1

Additional Context

  • Triggering value (process env): NO_PROXY / no_proxy = localhost,127.0.0.1,::1,[::1]. The [::1] entry alone (NO_PROXY=[::1]) is sufficient to reproduce.
  • Safe value verified: localhost,127.0.0.1,::1 (bare ::1, no brackets) works, including with the full proxy set (HTTP_PROXY/HTTPS_PROXY/ALL_PROXY=http://127.0.0.1:port).
  • Searched existing issues for NO_PROXY / brackets / httpx / invalid port and found no duplicate.
  • The crash happens inside httpx (_utils.URLPattern <- _client proxy-map build from get_environment_proxies), surfaced through Basic Memory because it is the shipped dependency. If httpx is vendored/pinned here, the fix belongs here; otherwise forwarding the minimal repro upstream to httpx would resolve it.

Possible Solution

Options, cheapest first:

  1. Sanitize NO_PROXY/no_proxy entries before they reach URLPattern: strip one pair of surrounding brackets from bracketed IPv6 literals ([::1] -> ::1), consistent with URL host parsing.
  2. Alternatively, catch InvalidURL per bypass entry and skip/warn instead of failing client construction.
  3. Alternatively, construct internal clients with trust_env=False (or explicit proxy=/no_proxy=) on paths that must never be affected by ambient proxy env.
  4. If the vendored httpx is old, pick up the upstream fix if one exists for bracketed NO_PROXY hosts.

Workaround for affected users: drop [::1] from NO_PROXY/no_proxy, keeping localhost,127.0.0.1,::1.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions