{"record":{"id":"c34b5e577fdcbcf8","repo":"netbirdio/netbird","slug":"aaaa-record-must-be-a-valid-ipv6-address","errorCode":null,"errorMessage":"AAAA record must be a valid IPv6 address","messagePattern":"AAAA record must be a valid IPv6 address","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"management/internals/modules/zones/records/record.go","lineNumber":126,"sourceCode":"\nfunc validateIPv4(content string) error {\n\tif content == \"\" {\n\t\treturn errors.New(\"A record is required\") //nolint:staticcheck\n\t}\n\tip := net.ParseIP(content)\n\tif ip == nil || ip.To4() == nil {\n\t\treturn errors.New(\"A record must be a valid IPv4 address\") //nolint:staticcheck\n\t}\n\treturn nil\n}\n\nfunc validateIPv6(content string) error {\n\tif content == \"\" {\n\t\treturn errors.New(\"AAAA record is required\")\n\t}\n\tip := net.ParseIP(content)\n\tif ip == nil || ip.To4() != nil {\n\t\treturn errors.New(\"AAAA record must be a valid IPv6 address\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":108,"sourceCodeEnd":130,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/management/internals/modules/zones/records/record.go#L108-L130","documentation":"validateIPv6 parses Content with net.ParseIP and rejects it when parsing fails or the result has a 4-byte form (ip.To4() != nil), i.e. when it is really IPv4. So an IPv4 literal like \"192.0.2.1\" under an AAAA record is rejected, as is a v4-mapped literal \"::ffff:192.0.2.1\" (its To4() is non-nil) and any malformed IPv6 string.","triggerScenarios":"Type \"AAAA\" with content \"192.0.2.1\", \"::ffff:192.0.2.1\", \"2001:db8\" (truncated), or a string that is not an IP at all.","commonSituations":"Pasting a v4 address into the AAAA field of a dual-stack form; assuming v4-mapped notation is an acceptable way to encode v4 targets in AAAA; zone files migrated with the wrong type column.","solutions":["Use a plain IPv6 literal, e.g. \"2001:db8::1\".","If the target only has IPv4, create an \"A\" record instead of AAAA.","Do not use v4-mapped \"::ffff:\" notation; this validator deliberately treats it as IPv4 and rejects it."],"exampleFix":"// before\n{\"name\": \"api\", \"type\": \"AAAA\", \"content\": \"192.0.2.1\"}\n// after\n{\"name\": \"api\", \"type\": \"A\", \"content\": \"192.0.2.1\"}","handlingStrategy":"validation","validationCode":"if api.DNSRecordType(req.Type) == api.DNSRecordTypeAAAA {\n    if ip := net.ParseIP(req.Content); ip == nil || ip.To4() != nil {\n        return fmt.Errorf(\"content %q is not an IPv6 address\", req.Content)\n    }\n}","typeGuard":"func isIPv6Literal(s string) bool {\n    ip := net.ParseIP(strings.TrimSpace(s))\n    return ip != nil && ip.To4() == nil\n}","tryCatchPattern":"if err := rec.Validate(); err != nil {\n    return respondBadRequest(err)\n}","preventionTips":["Detect v4 input in the AAAA field and offer to create an A record instead.","Avoid v4-mapped \"::ffff:\" literals; this validator rejects them."],"tags":["dns","zones","ipv6","validation"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}