sgl-project/sglang · error · ValueError

Bare IPv6 address without brackets is ambiguous: {addr!r}. U

Error message

Bare IPv6 address without brackets is ambiguous: {addr!r}. Use [{host}]:{port_str} instead.

What it means

The address contains multiple colons and the pre-split host portion is itself a valid IPv6 literal (e.g. '::1:8080' parses host='::1'). Because 'host:port' splitting is ambiguous for IPv6, the parser requires bracket notation.

Source

Thrown at python/sglang/srt/utils/network.py:551

            host = addr[1:close]
            if not _is_ipv6(host):
                raise ValueError(f"Invalid IPv6 address inside brackets: {host!r}")
            rest = addr[close + 1 :]
            if not rest.startswith(":") or len(rest) < 2:
                raise ValueError(
                    f"Expected ':port' after closing bracket, got: {rest!r}"
                )
            return NetworkAddress(host, _parse_port(rest[1:]))

        # --- Plain host:port (IPv4 / hostname) ---
        if ":" not in addr:
            raise ValueError(f"Missing port in address (expected host:port): {addr!r}")
        host, port_str = addr.rsplit(":", 1)
        if not host:
            raise ValueError(f"Empty host in address: {addr!r}")
        # Guard against bare IPv6 slipping through
        if ":" in host and _is_ipv6(host):
            raise ValueError(
                f"Bare IPv6 address without brackets is ambiguous: {addr!r}. "
                f"Use [{host}]:{port_str} instead."
            )
        return NetworkAddress(host, _parse_port(port_str))

    def __str__(self) -> str:
        return self.to_host_port_str()

    def __repr__(self) -> str:
        return f"NetworkAddress({self.host!r}, {self.port})"


def resolve_base_url(base_url: str, host: str, port: int) -> str:
    """Base URL a client sends to: ``base_url`` if set, else ``http://host:port``
    (IPv6-correct via :class:`NetworkAddress`)."""
    if base_url:
        return base_url
    return NetworkAddress(host, port).to_url()

View on GitHub (pinned to 0132848349)

Solutions

  1. Wrap the IPv6 part in brackets: '[::1]:8080'
  2. Use the exact form from the error message hint: '[{host}]:{port}'
  3. Audit config templates that interpolate IPv6 hosts to add brackets conditionally

Example fix

# before
addr = NetworkAddress.parse('2001:db8::1:8080')
# after
addr = NetworkAddress.parse('[2001:db8::1]:8080')
Defensive patterns

Strategy: validation

Validate before calling

import re
def bracket_if_ipv6(addr: str) -> str:
    if addr.count(':') > 1 and not addr.startswith('['):
        host, port = addr.rsplit(':', 1)
        return f'[{host}]:{port}'
    return addr

Type guard

null

Try / catch

try:
    NetworkAddress.parse(addr)
except ValueError as e:
    if 'without brackets' in str(e):
        host, port = addr.rsplit(':', 1)
        addr = f'[{host}]:{port}'
        NetworkAddress.parse(addr)

Prevention

When it happens

Trigger: NetworkAddress.parse('::1:8080') or '2001:db8::1:8080' — the rsplit leaves an IPv6-looking host with a port appended.

Common situations: Users writing IPv6 plus port the natural way without brackets; also NCCL/zookeeper/dist init addresses configured for IPv6 clusters.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/105a9aa19dcc0c64. Report an issue: GitHub.