{"record":{"id":"e9af8658e7a5b855","repo":"netbirdio/netbird","slug":"invalid-domain-name","errorCode":null,"errorMessage":"invalid domain name","messagePattern":"invalid domain name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"management/server/nameserver.go","lineNumber":24,"sourceCode":"\t\"fmt\"\n\t\"slices\"\n\t\"strings\"\n\t\"unicode/utf8\"\n\n\t\"github.com/rs/xid\"\n\n\tnbdns \"github.com/netbirdio/netbird/dns\"\n\t\"github.com/netbirdio/netbird/management/server/activity\"\n\t\"github.com/netbirdio/netbird/management/server/affectedpeers\"\n\t\"github.com/netbirdio/netbird/management/server/permissions/modules\"\n\t\"github.com/netbirdio/netbird/management/server/permissions/operations\"\n\t\"github.com/netbirdio/netbird/management/server/store\"\n\t\"github.com/netbirdio/netbird/management/server/types\"\n\tnbdomain \"github.com/netbirdio/netbird/shared/management/domain\"\n\t\"github.com/netbirdio/netbird/shared/management/status\"\n)\n\nvar errInvalidDomainName = errors.New(\"invalid domain name\")\n\n// GetNameServerGroup gets a nameserver group object from account and nameserver group IDs\nfunc (am *DefaultAccountManager) GetNameServerGroup(ctx context.Context, accountID, userID, nsGroupID string) (*nbdns.NameServerGroup, error) {\n\tallowed, ctx, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Nameservers, operations.Read)\n\tif err != nil {\n\t\treturn nil, status.NewPermissionValidationError(err)\n\t}\n\tif !allowed {\n\t\treturn nil, status.NewPermissionDeniedError()\n\t}\n\n\treturn am.Store.GetNameServerGroupByID(ctx, store.LockingStrengthNone, accountID, nsGroupID)\n}\n\n// CreateNameServerGroup creates and saves a new nameserver group\nfunc (am *DefaultAccountManager) CreateNameServerGroup(ctx context.Context, accountID string, name, description string, nameServerList []nbdns.NameServer, groups []string, primary bool, domains []string, enabled bool, userID string, searchDomainEnabled bool) (*nbdns.NameServerGroup, error) {\n\tallowed, ctx, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Nameservers, operations.Create)\n\tif err != nil {","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/management/server/nameserver.go#L6-L42","documentation":"errInvalidDomainName is a sentinel in nameserver.go, returned wrapped (\"invalid domain name: <detail>\") by validateDomain when nbdomain.ValidateDomains rejects a nameserver match domain. validateDomain first trims one trailing dot (FQDN form is allowed) and has already rejected \"*.\" wildcards, so this error comes from the domain itself: empty or over-long labels (>63 chars), total length limits, empty labels (\"a..b\"), or a FromString/idna conversion failure.","triggerScenarios":"CreateNameServerGroup/UpdateNameServerGroup (or the equivalent HTTP/gRPC handlers) with a domains entry like \"exa mple.com\", \"example..com\", a label over 63 chars, or an empty string after trimming the dot.","commonSituations":"Copy-pasted domains containing a space or an empty label; a match domain built by string concatenation that produced \"..\"; assuming nameserver match domains accept the same syntax as ACL/domain resources.","solutions":["Fix the domain string: single dots between labels, no spaces, each label 1-63 chars.","Punycode-convert unicode domains before sending; a trailing dot is fine here (it is trimmed).","Because the sentinel is wrapped with %w, inspect with errors.Is(err, errInvalidDomainName) when you need programmatic handling."],"exampleFix":"// before\nnsGroup.Domains = []string{\"exa mple.com\"}\n// after\nnsGroup.Domains = []string{\"example.com\"}","handlingStrategy":"validation","validationCode":"for _, d := range nsGroup.Domains {\n    trimmed := strings.TrimSuffix(d, \".\")\n    if _, err := nbdomain.ValidateDomains([]string{trimmed}); err != nil {\n        return fmt.Errorf(\"match domain %q invalid: %v\", d, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := am.SaveNameServerGroup(ctx, accountID, userID, nsGroup); err != nil {\n    if errors.Is(err, errInvalidDomainName) {\n        // point the user at the domains field; err text names the offending domain\n    }\n    return err\n}","preventionTips":["Validate match domains with shared/management/domain.ValidateDomains client-side; it also punycodes unicode.","A trailing dot is allowed for nameserver match domains, but double dots and spaces never are.","Run a regex lint on user input domains (no spaces, no empty labels) before submit."],"tags":["dns","nameservers","validation","management-api"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}