netbirdio/netbird · error

A record must be a valid IPv4 address

Error message

A record must be a valid IPv4 address

What it means

validateIPv4 parses Content with net.ParseIP and requires the result to have a 4-byte form (ip.To4() != nil). It fails for non-IP strings, malformed IPv4 ("192.0.2.256", "192.0.2"), and IPv6 literals (To4() is nil). Note the corollary: a v4-mapped IPv6 literal like "::ffff:192.0.2.1" is accepted because its To4() is non-nil.

Source

Thrown at management/internals/modules/zones/records/record.go:115

func (r *Record) EventMeta(zoneID, zoneName string) map[string]any {
	return map[string]any{
		"name":      r.Name,
		"type":      string(r.Type),
		"content":   r.Content,
		"ttl":       r.TTL,
		"zone_id":   zoneID,
		"zone_name": zoneName,
	}
}

func validateIPv4(content string) error {
	if content == "" {
		return errors.New("A record is required") //nolint:staticcheck
	}
	ip := net.ParseIP(content)
	if ip == nil || ip.To4() == nil {
		return errors.New("A record must be a valid IPv4 address") //nolint:staticcheck
	}
	return nil
}

func validateIPv6(content string) error {
	if content == "" {
		return errors.New("AAAA record is required")
	}
	ip := net.ParseIP(content)
	if ip == nil || ip.To4() != nil {
		return errors.New("AAAA record must be a valid IPv6 address")
	}
	return nil
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Use a dotted-quad IPv4 literal, e.g. "192.0.2.1".
  2. If the target is IPv6, change the record type to "AAAA" instead.
  3. Trim whitespace and reject hostnames client-side before submission.

Example fix

// before
{"name": "api", "type": "A", "content": "2001:db8::1"}
// after
{"name": "api", "type": "AAAA", "content": "2001:db8::1"}
Defensive patterns

Strategy: validation

Validate before calling

if api.DNSRecordType(req.Type) == api.DNSRecordTypeA {
    if ip := net.ParseIP(req.Content); ip == nil || ip.To4() == nil {
        return fmt.Errorf("content %q is not an IPv4 address", req.Content)
    }
}

Type guard

func isIPv4Literal(s string) bool {
    ip := net.ParseIP(strings.TrimSpace(s))
    return ip != nil && ip.To4() != nil
}

Try / catch

if err := rec.Validate(); err != nil {
    return respondBadRequest(err)
}

Prevention

When it happens

Trigger: Type "A" with content "2001:db8::1", "example.com", "192.0.2", or " 192.0.2.1" (leading space).

Common situations: Pasting a hostname where an address is expected; using the A type for an IPv6 target; address strings copied with whitespace or units from a spreadsheet.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/19a71818b4ea4a2b. Report an issue: GitHub.