{"record":{"id":"8d14c3e6a69abb45","repo":"hashicorp/nomad","slug":"invalid-ip-address-q","errorCode":null,"errorMessage":"invalid IP address %q","messagePattern":"invalid IP address %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/shared/hostnames/mount.go","lineNumber":54,"sourceCode":"ff00::0 ip6-mcastprefix\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\nff02::3 ip6-allhosts\n\n# this entry is the IP address and hostname of the allocation\n# shared with tasks in the task group's network\n%s %s\n`, hostsCfg.Address, hostsCfg.Hostname)\n\n\tif len(extraHosts) > 0 {\n\t\tcontent.WriteString(\"\\n# these entries are extra hosts added by the task config\")\n\t\tfor _, hostLine := range extraHosts {\n\t\t\thostsEntry := strings.SplitN(hostLine, \":\", 2)\n\t\t\tif len(hostsEntry) != 2 {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid hosts entry %q\", hostLine)\n\t\t\t}\n\t\t\tif net.ParseIP(hostsEntry[1]) == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid IP address %q\", hostLine)\n\t\t\t}\n\t\t\tcontent.WriteString(fmt.Sprintf(\"\\n%s %s\", hostsEntry[1], hostsEntry[0]))\n\t\t}\n\t\tcontent.WriteString(\"\\n\")\n\t}\n\n\tpath := filepath.Join(taskDir, \"hosts\")\n\n\t// tasks within an alloc should be able to share and modify the file, so\n\t// only write to it if it doesn't exist\n\tif _, err := os.Stat(path); os.IsNotExist(err) {\n\t\terr := os.WriteFile(path, []byte(content.String()), 0644)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// Note that we're not setting readonly. The file is in the task dir","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/shared/hostnames/mount.go#L36-L72","documentation":"After splitting an extra_hosts entry on the first colon, GenerateEtcHostsMount validates the second part with net.ParseIP. This error means the entry had a colon but the right-hand side is not a valid IPv4/IPv6 address literal.","triggerScenarios":"extra_hosts entry like \"myhost:not-an-ip\", \"myhost:192.168.1\", \"myhost:example.com\" (hostnames on the wrong side), or a reversed \"IP:hostname\" pair, reaching GenerateEtcHostsMount via createContainerConfig.","commonSituations":"Swapping the mapping order (Docker uses hostname:IP but users write IP:hostname); truncated IPs from variable substitution; IPv6 zones or shorthand net.ParseIP rejects (e.g. missing brackets or bad compression); using DNS names instead of IPs.","solutions":["Ensure the format is \"hostname:valid-IP\" — the value after the colon must parse as an IP (e.g. \"web:10.0.0.5\")","Swap the fields if you wrote the IP first","Use a resolvable IP, not a DNS name — extra_hosts only accepts literal addresses","Check IPv6 entries parse with net.ParseIP (use full/compressed valid forms, no zone IDs)"],"exampleFix":"// before\nextra_hosts = [\"10.0.0.5:myhost\"]\n// after\nextra_hosts = [\"myhost:10.0.0.5\"]","handlingStrategy":"validation","validationCode":"func validExtraHostIPs(hosts []string) error {\n    for _, h := range hosts {\n        parts := strings.SplitN(h, \":\", 2)\n        if len(parts) == 2 && net.ParseIP(parts[1]) == nil {\n            return fmt.Errorf(\"extra host %q: %q is not a valid IP\", h, parts[1])\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember the order is hostname:IP, not IP:hostname","Only literal IPv4/IPv6 addresses are accepted — never DNS names","Check IPv6 entries with net.ParseIP locally before submitting the job"],"tags":["docker","networking","etc-hosts","config-validation"],"backgroundTag":"invalid-ip-address","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}