valyala/fasthttp · error

invalid host %q

Error message

invalid host %q

What it means

For non-bracketed hosts, parseHost rejects any host containing '[' or ']' with "invalid host %q", since brackets are only legal around IPv6 literals. It also rejects multiple ':' port delimiters with a related error. This keeps regfile-style hosts strict and unambiguous.

Source

Thrown at uri.go:468

		zone := bytes.Index(host[:i], []byte("%25"))
		if zone >= 0 {
			host1, err := unescape(host[:zone], encodeHost)
			if err != nil {
				return nil, err
			}
			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
	}

View on GitHub (pinned to c96f600972)

Solutions

  1. Strip or percent-encode stray brackets before parsing
  2. Validate the host with net/url.Parse or a host regex prior to fasthttp Parse
  3. Reject the request with 400 when brackets are not part of a valid IPv6 literal
  4. Fix URL-construction code that inserts unescaped values into host position

Example fix

// before
var u uri.URI
u.Parse(nil, nil, []byte("http://ex[ample.com/")) // stray '['
// after
raw := strings.ReplaceAll("http://ex[ample.com/", "[", "%5B") // encode or fix host
var u uri.URI
err := u.Parse(nil, nil, []byte(raw))
Defensive patterns

Strategy: validation

Validate before calling

func hostHasStrayBrackets(host string) bool {
    if strings.HasPrefix(host, "[") && strings.Contains(host, "]") {
        return false // legit IPv6 literal form
    }
    return strings.ContainsAny(host, "[]")
}

Try / catch

var u uri.URI
if err := u.Parse(nil, nil, raw); err != nil {
    if strings.HasPrefix(err.Error(), "invalid host") {
        return fmt.Errorf("rejecting bad host: %w", err) // map to 400
    }
    return err
}

Prevention

When it happens

Trigger: URI.Parse with hosts like "http://ex[ample.com/", "http://host]x/", or a stray unmatched bracket anywhere in a non-IPv6 host.

Common situations: Client-supplied Host headers/targets with stray brackets; template or concatenation bugs when building URLs; malformed proxy-form targets forwarded by upstream proxies.

Related errors


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/89df555535860b78. Report an issue: GitHub.