valyala/fasthttp · error
invalid host %q with multiple port delimiters
Error message
invalid host %q with multiple port delimiters
What it means
url.Parse's parseHost validates the host portion of an authority. After locating the last ':' (candidate port delimiter), it rejects the host if another ':' appears before it. Bracketed IPv6 hosts are handled earlier, so any remaining multi-colon host is invalid.
Source
Thrown at uri.go:473
}
host2, err := unescape(host[zone:i], encodeZone)
if err != nil {
return nil, err
}
host3, err := unescape(host[i:], encodeHost)
if err != nil {
return nil, err
}
return append(host1, append(host2, host3...)...), nil
}
} else {
if bytes.IndexByte(host, '[') >= 0 || bytes.IndexByte(host, ']') >= 0 {
return nil, fmt.Errorf("invalid host %q", host)
}
if i := bytes.LastIndexByte(host, ':'); i != -1 {
if bytes.IndexByte(host[:i], ':') != -1 {
return nil, fmt.Errorf("invalid host %q with multiple port delimiters", host)
}
colonPort := host[i:]
if !validOptionalPort(colonPort) {
return nil, fmt.Errorf("invalid port %q after host", colonPort)
}
}
}
var err error
if host, err = unescape(host, encodeHost); err != nil {
return nil, err
}
if err = validateIPv6Literal(host); err != nil {
return nil, err
}
return host, nil
}View on GitHub (pinned to c96f600972)
Solutions
- Wrap IPv6 literals in square brackets: http://[::1]:8080/
- Remove the duplicate port delimiter; pass only host:port once
- If input comes from config, split and validate host/port separately before building the URL
Example fix
// before
u, err := url.Parse("http://::1:8080/path")
// after
u, err := url.Parse("http://[::1]:8080/path") Defensive patterns
Strategy: validation
Validate before calling
func validURLHost(raw string) bool {
u, err := url.Parse(raw)
return err == nil && u.Host != ""
}
// call before using the URL in the API Type guard
func isBracketedIPv6(host string) bool {
return strings.HasPrefix(host, "[") && strings.Contains(host, "]")
} Try / catch
u, err := url.Parse(rawURL)
if err != nil {
var ue *url.Error
if errors.As(err, &ue) && strings.Contains(ue.Err.Error(), "invalid host") {
// normalize: bracket IPv6 or strip extra ':'
}
return fmt.Errorf("bad URL host in %q: %w", rawURL, err)
} Prevention
- Always bracket IPv6 literals in URLs
- Build URLs with url.URL{Host: ...} instead of string concatenation
- Never append a port to a value that may already contain ':'
When it happens
Trigger: Parsing a URL whose host contains two or more colons outside brackets, e.g. http.Parse("http://host:8080:90/") or "http://::1/" (unbracketed IPv6 literal).
Common situations: IPv6 addresses pasted without [ ] brackets; concatenating host and port strings twice (host+":"+port where host already has a port); proxy strings like host:port accidentally used as a URL host.
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/ae19bdd642015e20.
Report an issue: GitHub.