tsenart/vegeta · error
host %s is not an IP address
Error message
host %s is not an IP address
What it means
vegeta's internal resolver, used with -connect-to / custom DNS handling, requires each address host to be a literal IP because it bypasses normal name resolution. normalizeAddrs parses each host with net.ParseIP and fails the whole resolution if any host is a hostname rather than an IP.
Source
Thrown at internal/resolver/resolver.go:62
addr += ":53"
}
// validate addr is a valid host:port
host, portstr, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
// validate valid port.
_, err = strconv.ParseUint(portstr, 10, 16)
if err != nil {
return nil, err
}
// make sure host is an ip.
ip := net.ParseIP(host)
if ip == nil {
return nil, fmt.Errorf("host %s is not an IP address", host)
}
normal[i] = addr
}
return normal, nil
}
// ignore the third parameter, as this represents the dns server address that
// we are overriding.
func (r *resolver) dial(ctx context.Context, network, _ string) (net.Conn, error) {
return r.dialer.DialContext(ctx, network, r.address())
}
func (r *resolver) address() string {
return r.addrs[atomic.AddUint64(&r.idx, 1)%uint64(len(r.addrs))]
}
View on GitHub (pinned to cf58112690)
Solutions
- Replace hostnames with IP literals, e.g. 93.184.216.34:80 instead of example.com:80.
- Resolve the hostname yourself (dig/nslookup or net.LookupHost) and pass the resulting IP.
- If you need hostname behavior, use the default resolver path instead of the IP-based one.
- Check each entry in the address map before constructing the resolver.
Example fix
// before -connect-to=example.com:80:127.0.0.1:8080 # IP-requiring resolver path // after -connect-to=93.184.216.34:80:127.0.0.1:8080
Defensive patterns
Strategy: validation
Validate before calling
func allIPs(addrs []string) bool {
for _, addr := range addrs {
host, _, err := net.SplitHostPort(addr)
if err != nil || net.ParseIP(host) == nil {
return false
}
}
return true
} Prevention
- Use IP literals, not hostnames, wherever the resolver requires IPs.
- Pre-resolve DNS names with net.LookupHost before configuring.
- Document that -connect-to paths may bypass DNS.
- Validate each host with net.ParseIP before constructing the resolver.
When it happens
Trigger: Calling NewResolver (or the anonymous function it calls) with address lists containing hostnames like "example.com:80" instead of IP literals; commonly reached by passing hostnames in -connect-to mappings.
Common situations: Assuming -connect-to accepts DNS names; config files with domain names; confusing the resolver's IP-only requirement with normal client DNS behavior.
Related errors
- must specify at least resolver address
- invalid -connect-to %q, expected format: %s
- invalid source address expression [%s], expected address:por
- invalid destination address expression [%s], expected addres
AI-assisted analysis of tsenart/vegeta@cf58112690 (2026-08-31).
Data as JSON: /api/errors/63712e029b1c88e1.
Report an issue: GitHub.