juanfont/headscale · error
dst=%q: port range %q: %w
Error message
dst=%q: port range %q: %w
What it means
While unmarshalling a test destination (host:port form), the part after the colon failed parsePortRange. The error is prefixed with the full original destination and the offending port substring so the exact bad fragment is visible.
Source
Thrown at hscontrol/policy/v2/types.go:891
switch vs := v.(type) {
case string:
var (
portsPart string
err error
)
originalDst := vs
if strings.Contains(vs, ":") {
vs, portsPart, err = splitDestinationAndPort(vs)
if err != nil {
return err
}
ports, err := parsePortRange(portsPart)
if err != nil {
return fmt.Errorf(
"dst=%q: port range %q: %w",
originalDst, portsPart, err,
)
}
ve.Ports = ports
} else {
return ErrHostportMissingColon
}
ve.Alias, err = parseAlias(vs)
if err != nil {
return err
}
if err := ve.Validate(); err != nil { //nolint:noinlineerr
return err
}View on GitHub (pinned to 565fd254d0)
Solutions
- Use a single port or a simple 'low-high' range: 'web:80', 'web:8080-8090'.
- Split comma-separated ports into separate destination entries.
- Keep ports within 0-65535 and range bounds ordered.
Example fix
// before "accept": ["web:80,443"] // after "accept": ["web:80", "web:443"]
Defensive patterns
Strategy: validation
Validate before calling
var portRangeRe = regexp.MustCompile(`^[0-9]+(-[0-9]+)?$`)
_, ports := splitDestinationAndPortSafe(dst)
if !portRangeRe.MatchString(ports) {
return fmt.Errorf("bad ports %q in %q; want N or N-M", ports, dst)
} Try / catch
if err := v2.UnmarshalTestDestination(dst, &ve); err != nil {
if strings.Contains(err.Error(), "port range") {
// error shows dst= and the exact bad fragment; fix that entry
}
return err
} Prevention
- One port or one range per destination; separate entries for more.
- Numeric ports only (0-65535), '-' as the range separator.
- Schema-lint the tests section in CI.
When it happens
Trigger: Destinations like 'web:80-90-100' (double range), 'web:abc', 'web:70000', or 'web:0x50'. splitDestinationAndPort succeeds but parsePortRange(portsPart) errors in the test-destination unmarshaller.
Common situations: Comma-spliced ports ('web:80,443' parsed as one fragment), ranges written with '..' instead of '-', port numbers from config copied in decimal-with-suffix form.
Related errors
- invalid destination %q: %w
- port range %q: %w
- %w, got: %v(%d)
- protocol does not support specific ports
- invalid alias: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/a9293e541fed781c.
Report an issue: GitHub.