{"record":{"id":"45aa81585402b82f","repo":"micro/go-micro","slug":"hostname-q-is-not-a-fully-qualified-domain-name","errorCode":null,"errorMessage":"hostName %q is not a fully-qualified domain name: %v","messagePattern":"hostName %q is not a fully-qualified domain name: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/util/mdns/zone.go","lineNumber":94,"sourceCode":"\t// Set default domain\n\tif domain == \"\" {\n\t\tdomain = \"local.\"\n\t}\n\tif err := validateFQDN(domain); err != nil {\n\t\treturn nil, fmt.Errorf(\"domain %q is not a fully-qualified domain name: %v\", domain, err)\n\t}\n\n\t// Get host information if no host is specified.\n\tif hostName == \"\" {\n\t\tvar err error\n\t\thostName, err = os.Hostname()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"could not determine host: %v\", err)\n\t\t}\n\t\thostName = fmt.Sprintf(\"%s.\", hostName)\n\t}\n\tif err := validateFQDN(hostName); err != nil {\n\t\treturn nil, fmt.Errorf(\"hostName %q is not a fully-qualified domain name: %v\", hostName, err)\n\t}\n\n\tif len(ips) == 0 {\n\t\tvar err error\n\t\tips, err = net.LookupIP(trimDot(hostName))\n\t\tif err != nil {\n\t\t\t// Try appending the host domain suffix and lookup again\n\t\t\t// (required for Linux-based hosts)\n\t\t\ttmpHostName := fmt.Sprintf(\"%s%s\", hostName, domain)\n\n\t\t\tips, err = net.LookupIP(trimDot(tmpHostName))\n\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"could not determine host IP addresses for %s\", hostName)\n\t\t\t}\n\t\t}\n\t}\n\tfor _, ip := range ips {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/internal/util/mdns/zone.go#L76-L112","documentation":"NewMDNSService validates the (explicit or auto-detected) hostName with validateFQDN; a non-empty hostName that does not end in a period (or is otherwise invalid) produces this wrapped error. The %v carries the specific validation failure.","triggerScenarios":"Passing hostName like \"myhost.local\" (no trailing dot) or \"\" where the auto-detected path was skipped; directly supplying a hostName that fails validateFQDN after NewMDNSService defaults were applied.","commonSituations":"Building hostName from config values that omit the trailing dot; concatenating hostname and domain in the wrong order so the dot is lost; migrations from libraries that accept dot-less hostnames.","solutions":["Ensure hostName ends in '.': hostName = strings.TrimSuffix(hostName, \".\") + \".\"","Leave hostName empty to let NewMDNSService auto-detect and correctly append the dot","Normalize hostName during config load with the same rule as validateFQDN"],"exampleFix":"// before\nsvc, err := NewMDNSService(\"myapp\", \"_http._tcp\", \"local.\", \"myhost.local\", 8080, ips, nil)\n// after\nsvc, err := NewMDNSService(\"myapp\", \"_http._tcp\", \"local.\", \"myhost.local.\", 8080, ips, nil)","handlingStrategy":"validation","validationCode":"func normalizeHostName(h string) string {\n\tif h == \"\" { return \"\" } // let the library auto-detect\n\tif !strings.HasSuffix(h, \".\") { return h + \".\" }\n\treturn h\n}\n// hostName = normalizeHostName(cfg.HostName)","typeGuard":"func isValidHostName(h string) bool { return len(h) > 0 && h[len(h)-1] == '.' }","tryCatchPattern":"svc, err := NewMDNSService(instance, service, domain, hostName, port, ips, txt)\nif err != nil {\n\tif strings.Contains(err.Error(), \"hostName\") && strings.Contains(err.Error(), \"fully-qualified\") {\n\t\treturn fmt.Errorf(\"hostname must end in a trailing dot, e.g. 'myhost.local.': %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Normalize all hostnames to FQDN form (trailing dot) before calling NewMDNSService","Prefer empty hostName to let the library auto-detect and format correctly","Add a validation test that asserts every configured hostname ends in '.'"],"tags":["validation","mdns","fqdn","hostname"],"backgroundTag":"fqdn-missing-trailing-dot","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}