netbirdio/netbird · error
not a valid host, subnet, or domain
Error message
not a valid host, subnet, or domain
What it means
types.GetResourceType classifies a network resource address by trying netip.ParsePrefix (a CIDR is a Host if /32 or /128, otherwise a Subnet), then netip.ParseAddr (bare IP is a Host), then nbDomain.ValidateDomains (a Domain, with punycode conversion). When all three fail it returns this error. Callers such as UpdateResource (manager.go:215) wrap it as "failed to get resource type: ...".
Source
Thrown at management/server/networks/resources/types/resource.go:196
// GetResourceType returns the type of the resource based on the address
func GetResourceType(address string) (NetworkResourceType, string, netip.Prefix, error) {
if prefix, err := netip.ParsePrefix(address); err == nil {
if prefix.Bits() == 32 || prefix.Bits() == 128 {
return Host, "", prefix, nil
}
return Subnet, "", prefix, nil
}
if ip, err := netip.ParseAddr(address); err == nil {
return Host, "", netip.PrefixFrom(ip, ip.BitLen()), nil
}
if _, err := nbDomain.ValidateDomains([]string{address}); err == nil {
return Domain, address, netip.Prefix{}, nil
}
return "", "", netip.Prefix{}, errors.New("not a valid host, subnet, or domain")
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Send a bare IP ("192.0.2.1"), a CIDR ("10.0.0.0/8"), or a plain domain ("example.com").
- Strip schemes, ports, paths, and whitespace before submitting an address.
- Punycode-convert unicode domains or let a client-side domain validator do it before the request.
Example fix
// before resource.Address = "https://example.com" // after resource.Address = "example.com"
Defensive patterns
Strategy: validation
Validate before calling
func isClassifiableAddress(a string) error {
if _, err := netip.ParsePrefix(a); err == nil { return nil }
if _, err := netip.ParseAddr(a); err == nil { return nil }
if _, err := domain.ValidateDomains([]string{a}); err == nil { return nil }
return fmt.Errorf("%q is not a valid host, subnet, or domain", a)
}
if err := isClassifiableAddress(resource.Address); err != nil {
return err
} Type guard
func validResourceAddress(a string) bool {
if _, err := netip.ParsePrefix(a); err == nil { return true }
if _, err := netip.ParseAddr(a); err == nil { return true }
_, err := domain.ValidateDomains([]string{a})
return err == nil
} Try / catch
if _, _, _, err := types.GetResourceType(resource.Address); err != nil {
return fmt.Errorf("failed to get resource type: %w", err) // surfaces 'not a valid host, subnet, or domain'
} Prevention
- Offer three explicit input modes (IP, CIDR, domain) in UIs instead of one free-text field.
- Strip schemes, ports, paths, and whitespace from addresses before submitting.
- For subnets always include the /bits suffix; a bare address is classified as a Host.
When it happens
Trigger: CreateResource/UpdateResource with an address that is none of the three forms: "" (empty), "192.0.2.1/33" (invalid prefix bits), "example.com/" (trailing slash), "host name" (space), "192.0.2.1:8080" (port suffix), or "not_a domain!".
Common situations: Free-text address fields in UIs or scripts with no client-side normalization; forgetting the CIDR slash for subnets ("10.0.0.0" parses as a Host, not a subnet); pasting URLs ("https://example.com") instead of bare domains; empty submissions from forms.
Related errors
- resource not part of network
- router not part of network
- peer and peer_groups cannot be set at the same time
- either peer or peer_groups must be provided
- failed to select networks: %v
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/436399b6c2b27f85.
Report an issue: GitHub.