{"record":{"id":"2a51253a20968b07","repo":"docker/cli","slug":"bad-format-for-add-host-q","errorCode":null,"errorMessage":"bad format for add-host: %q","messagePattern":"bad format for add-host: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"opts/hosts.go","lineNumber":174,"sourceCode":"//\tmy-hostname=::1\n//\tmy-hostname:[::1]\n//\n// For compatibility with the API server, this function normalises the given\n// argument to use the ':' separator and strip square brackets enclosing the\n// address.\nfunc ValidateExtraHost(val string) (string, error) {\n\tk, v, ok := strings.Cut(val, \"=\")\n\tif !ok {\n\t\t// allow for IPv6 addresses in extra hosts by only splitting on first \":\"\n\t\tk, v, ok = strings.Cut(val, \":\")\n\t}\n\t// Check that a hostname was given, and that it doesn't contain a \":\". (Colon\n\t// isn't allowed in a hostname, along with many other characters. It's\n\t// special-cased here because the API server doesn't know about '=' separators in\n\t// '--add-host'. So, it'll split at the first colon and generate a strange error\n\t// message.)\n\tif !ok || k == \"\" || strings.Contains(k, \":\") {\n\t\treturn \"\", fmt.Errorf(\"bad format for add-host: %q\", val)\n\t}\n\t// Skip IPaddr validation for \"host-gateway\" string\n\tif v != hostGatewayName {\n\t\t// If the address is enclosed in square brackets, extract it (for IPv6, but\n\t\t// permit it for IPv4 as well; we don't know the address family here, but it's\n\t\t// unambiguous).\n\t\tif len(v) > 2 && v[0] == '[' && v[len(v)-1] == ']' {\n\t\t\tv = v[1 : len(v)-1]\n\t\t}\n\t\t// ValidateIPAddress returns the address in canonical form (for example,\n\t\t// 0:0:0:0:0:0:0:1 -> ::1). But, stick with the original form, to avoid\n\t\t// surprising a user who's expecting to see the address they supplied in the\n\t\t// output of 'docker inspect' or '/etc/hosts'.\n\t\tif _, err := ValidateIPAddress(v); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"invalid IP address in add-host: %q\", v)\n\t\t}\n\t}\n\t// This result is passed directly to the API, the daemon doesn't accept the '='","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/opts/hosts.go#L156-L192","documentation":"Returned by ValidateExtraHost (opts/hosts.go:174) when a `--add-host` value cannot be split into hostname:IP (or hostname=IP). The function first tries '=' then falls back to the first ':'; this error fires when neither split succeeds, the hostname (key) is empty, or the hostname itself contains a colon. It guards the well-known `name:ip` extra-hosts format that the daemon later writes into /etc/hosts.","triggerScenarios":"Calling ValidateExtraHost with a value that has no '=' and no ':', an empty hostname half (e.g. `:127.0.0.1`), or a hostname containing ':' (which would confuse the API server's colon-based split). ListOpts using ValidateExtraHost as its validator hits this on each Set().","commonSituations":"Forgetting the IP (`myhost`), using a comma or space as separator (`myhost,127.0.0.1`), pasting an IPv6 literal as the name side, or trailing separator (`myhost:`).","solutions":["Format as name:ip, e.g. my-host:127.0.0.1.","For IPv6 use name:::1, name=::1, or name=[::1] (all accepted).","Use the literal host-gateway as the value to skip IP validation: my-host:host-gateway.","Ensure the name part has no colon and is non-empty."],"exampleFix":"// before\nv, err := opts.ValidateExtraHost(\"myhost\")\n\n// after\nv, err := opts.ValidateExtraHost(\"myhost:127.0.0.1\")","handlingStrategy":"validation","validationCode":"// validateExtraHostShape checks the name:ip / name=ip shape before calling ValidateExtraHost.\nfunc validateExtraHostShape(val string) error {\n    k, _, hasEq := strings.Cut(val, \"=\")\n    if !hasEq {\n        k, _, hasEq = strings.Cut(val, \":\")\n    }\n    if !hasEq || strings.TrimSpace(k) == \"\" || strings.Contains(k, \":\") {\n        return fmt.Errorf(\"expected name:ip or name=ip, got %q\", val)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"for _, h := range cfg.AddHosts {\n    if _, err := opts.ValidateExtraHost(h); err != nil {\n        return fmt.Errorf(\"bad add-host %q: %w\", h, err)\n    }\n}","preventionTips":["Use name:ip consistently; reserve name=ip for IPv6 to avoid colon ambiguity.","Validate add-host entries in your config loader before they reach the daemon request.","Reject entries whose name contains a colon at config-parse time."],"tags":["networking","host","docker","add-host","parse","configuration"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}