netbirdio/netbird · error

invalid record type, must be A, AAAA, or CNAME

Error message

invalid record type, must be A, AAAA, or CNAME

What it means

The per-type switch in Validate() has no matching case for the supplied Type and falls to default. Only the exact constants "A", "AAAA", and "CNAME" (records.RecordTypeA/AAAA/CNAME) are accepted; matching is case-sensitive, so "a", "txt", "MX", "SRV" all land here.

Source

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

	if r.Type == "" {
		return errors.New("record type is required")
	}

	switch r.Type {
	case RecordTypeA:
		if err := validateIPv4(r.Content); err != nil {
			return err
		}
	case RecordTypeAAAA:
		if err := validateIPv6(r.Content); err != nil {
			return err
		}
	case RecordTypeCNAME:
		if !domain.IsValidDomainNoWildcard(r.Content) {
			return errors.New("invalid CNAME target format")
		}
	default:
		return errors.New("invalid record type, must be A, AAAA, or CNAME")
	}

	if r.TTL < 0 {
		return errors.New("TTL cannot be negative")
	}

	return nil
}

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,
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Change the type to exactly "A", "AAAA", or "CNAME" (uppercase, no surrounding whitespace).
  2. Drop or externally host record types this zone model does not support before importing.
  3. Constrain the client's type picker to the three supported values so invalid ones cannot be sent.

Example fix

// before
{"name": "api", "type": "txt", "content": "v=spf1 -all"}
// after
{"name": "api", "type": "CNAME", "content": "target.example.com"}
Defensive patterns

Strategy: type-guard

Validate before calling

if !isValidRecordType(string(req.Type)) {
    return fmt.Errorf("unsupported record type %q, use A, AAAA, or CNAME", req.Type)
}

Type guard

func isValidRecordType(t string) bool {
    switch records.RecordType(t) {
    case records.RecordTypeA, records.RecordTypeAAAA, records.RecordTypeCNAME:
        return true
    }
    return false
}

Try / catch

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

Prevention

When it happens

Trigger: A record body with "type": "TXT", "SRV", "MX", or lowercase "a"/"cname"; importing a zone export from a provider with record types NetBird zones do not support.

Common situations: Migrating DNS data from BIND/Route53 style exports that include TXT/SRV/MX records; a client normalizing types to lowercase; typos like "AAAA " with whitespace (no trimming is done).

Related errors


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