valyala/fasthttp · error

invalid host %q: use a host client for multiple hosts

Error message

invalid host %q: use a host client for multiple hosts

What it means

The generic fasthttp Client routes requests to per-host HostClients created on demand. A URI whose host contains a comma cannot map to a single host, so Do rejects it and tells you to use a HostClient bound to a specific host instead.

Source

Thrown at client.go:550

// Response is ignored if resp is nil.
//
// The function doesn't follow redirects. Use Get* for following redirects.
//
// ErrNoFreeConns is returned if all Client.MaxConnsPerHost connections
// to the requested host are busy.
//
// It is recommended obtaining req and resp via AcquireRequest
// and AcquireResponse in performance-critical code.
func (c *Client) Do(req *Request, resp *Response) error {
	uri := req.URI()
	if uri == nil {
		return ErrorInvalidURI
	}

	host := uri.Host()

	if bytes.ContainsRune(host, ',') {
		return fmt.Errorf("invalid host %q: use a host client for multiple hosts", host)
	}

	isTLS := false
	if uri.isHTTPS() {
		isTLS = true
	} else if !uri.isHTTP() {
		return fmt.Errorf("unsupported protocol %q. http and https are supported", uri.Scheme())
	}

	c.mOnce.Do(func() {
		c.m = make(map[string]*HostClient)
		c.ms = make(map[string]*HostClient)
	})
	hc, err := c.hostClient(host, isTLS)
	if err != nil {
		return err
	}

View on GitHub (pinned to c96f600972)

Solutions

  1. Use fasthttphost-style HostClient with c.Host set explicitly, or fasthttp.HostClient{Addr: ...} per target
  2. Split the comma-joined value and pick/iterate one host per request
  3. Sanitize or reject comma characters when constructing URIs from user input
  4. Fix the code path that interpolates a Host header or config list directly into the URL

Example fix

// before
req.SetRequestURI("http://" + strings.Join(backends, ",") + "/api")
client.Do(req, resp)
// after
hc := &fasthttp.HostClient{Addr: pickBackend(backends)}
req.SetRequestURI("http://" + hc.Addr + "/api")
hc.Do(req, resp)
Defensive patterns

Strategy: validation

Validate before calling

u, _ := url.Parse(req.URI().String())
if strings.Contains(u.Host, ",") { return errors.New("multiple hosts in URI; use HostClient") }

Type guard

func isSingleHostURI(uri string) bool {
    u, err := url.Parse(uri)
    return err == nil && !strings.Contains(u.Host, ",")
}

Try / catch

err := client.Do(req, resp)
if err != nil {
    if strings.Contains(err.Error(), "use a host client for multiple hosts") {
        // fall back to a per-host HostClient
    }
}

Prevention

When it happens

Trigger: Calling client.Do/DoTimeout/DoDeadline with a request whose RequestURI/URL host contains ',', e.g. "http://host1,host2/path" or a comma-joined host list copied from a proxy config or Host header.

Common situations: Building a URL by joining multiple backends with commas, reusing a Host header from an inbound request that contained a comma list, load-balancer-style config pasted into the URL.

Related errors


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