grafana/k6 · error
mixed IP range format: {s}
Error message
mixed IP range format: {s} What it means
Returned by ipBlockFromRange (lib/types/ipblock.go:49-51) when both endpoints of an IP range parse as IPs but one is IPv4 and the other IPv6 ((ip0.To4() == nil) != (ip1.To4() == nil) XOR check). A single ipBlock tracks one address family (block.ipv6 is set from ip0 alone in ipBlockFromTwoIPs), so mixed-family ranges cannot be represented and are rejected.
Source
Thrown at lib/types/ipblock.go:50
return ipBlockFromRange(s)
case strings.Contains(s, "/"):
return ipBlockFromCIDR(s)
default:
if net.ParseIP(s) == nil {
return nil, fmt.Errorf("%s is not a valid IP, IP range or CIDR", s)
}
return ipBlockFromRange(s + "-" + s)
}
}
func ipBlockFromRange(s string) (*ipBlock, error) {
ip0Str, ip1Str, _ := strings.Cut(s, "-")
ip0, ip1 := net.ParseIP(ip0Str), net.ParseIP(ip1Str)
if ip0 == nil || ip1 == nil {
return nil, errors.New("wrong IP range format: " + s)
}
if (ip0.To4() == nil) != (ip1.To4() == nil) { // XOR
return nil, errors.New("mixed IP range format: " + s)
}
block := ipBlockFromTwoIPs(ip0, ip1)
if block.count.Sign() <= 0 {
return nil, errors.New("negative IP range: " + s)
}
return block, nil
}
func ipBlockFromTwoIPs(ip0, ip1 net.IP) *ipBlock {
// This code doesn't do any checks on the validity of the arguments, that should be
// done before and/or after it is called
var block ipBlock
block.firstIP = new(big.Int)
block.count = new(big.Int)
block.ipv6 = ip0.To4() == nil
if block.ipv6 {
block.firstIP.SetBytes(ip0.To16())View on GitHub (pinned to 93accf6570)
Solutions
- Keep both endpoints in the same family, e.g. '::1-::ff' or '10.0.0.1-10.0.0.10'
- If both families are needed, define two separate blocks, one per family
Example fix
// before
block, err := getIPBlock("10.0.0.1-::ffff")
// after
block, err := getIPBlock("10.0.0.1-10.0.0.10") Defensive patterns
Strategy: validation
Validate before calling
// Go: ensure both endpoints are the same address family
func sameFamily(s string) bool {
a, b, _ := strings.Cut(s, "-")
ipa, ipb := net.ParseIP(a), net.ParseIP(b)
return ipa != nil && ipb != nil && ((ipa.To4() == nil) == (ipb.To4() == nil))
} Prevention
- Do not mix IPv4 and IPv6 endpoints in one range; declare one block per family
- When templating dual-stack configs, tag start/end fields with the family they came from
When it happens
Trigger: Calling getIPBlock with something like '::1-192.168.0.10' or '10.0.0.1-ffff::2' — both sides syntactically valid IPs, but of different families.
Common situations: Config generation joining a v4 start and v6 end from different variables; dual-stack configs where a template's start/end fields were filled from different address families.
Related errors
- wrong IP range format: {s}
- negative IP range: {s}
- urlTemplate must contain {key} placeholder
- urlTemplate must be an absolute URL with a scheme (e.g., htt
- timeout must be greater than 0
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/d5e8a4c13c16310f.
Report an issue: GitHub.