{"record":{"id":"c5ad711638d9dacc","repo":"gastownhall/beads","slug":"addr-q-host-must-be-a-numeric-ip-literal-not","errorCode":null,"errorMessage":"--addr %q: host must be a numeric IP literal, not a name — use 127.0.0.1 rather than localhost","messagePattern":"--addr %q: host must be a numeric IP literal, not a name — use 127\\.0\\.0\\.1 rather than localhost","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/httpapi/server.go","lineNumber":448,"sourceCode":"// Dolt child already lives under (validateManagedServerConfigPolicy in\n// cmd/bd/proxied_server.go): the host must be a NUMERIC IP literal.\n//\n// Hostnames are refused, \"localhost\" included. A name is not a listener\n// specification — it resolves to whatever the host's resolver says today, so\n// the operator cannot tell from the flag which interfaces they just opened.\n// Unix sockets are not supported at all; they fail here because they do not\n// parse as host:port.\nfunc ValidateBindAddr(addr string, allowNonLoopback bool) (net.IP, error) {\n\thost, port, err := net.SplitHostPort(addr)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"--addr %q must be HOST:PORT with a numeric IP literal host (unix sockets are not supported): %w\", addr, err)\n\t}\n\tif _, err := strconv.ParseUint(port, 10, 16); err != nil {\n\t\treturn nil, fmt.Errorf(\"--addr %q: port must be a number from 0 to 65535 (0 picks an ephemeral port)\", addr)\n\t}\n\tip := net.ParseIP(host)\n\tif ip == nil {\n\t\treturn nil, fmt.Errorf(\"--addr %q: host must be a numeric IP literal, not a name — use 127.0.0.1 rather than localhost\", addr)\n\t}\n\tif !ip.IsLoopback() && !allowNonLoopback {\n\t\treturn nil, fmt.Errorf(\"--addr %q binds beyond loopback, which requires --allow-non-loopback (and, with it, --auth-token-file)\", addr)\n\t}\n\treturn ip, nil\n}\n\n// Listen validates the configuration, binds the listener, and reports the\n// bound address on stdout and the startup state on stderr. It does not accept\n// anything until Serve runs.\n//\n// There is no lock file, pid file or discovery file: bd serve is\n// operator-invoked and the TCP bind IS the mutual exclusion, so a second\n// instance on the same fixed port fails here with the operating system's own\n// address-in-use error. (Under the ephemeral default that exclusion does not\n// exist — N instances simply run on N ports — which is why fixed ports are the\n// deployment recommendation.)\nfunc Listen(cfg Config) (*Server, error) {","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/httpapi/server.go#L430-L466","documentation":"ValidateBindAddr requires the host portion of --addr to be a numeric IP literal. net.ParseIP failed on the host, meaning a DNS name (like 'localhost') was supplied. The library deliberately refuses names and suggests 127.0.0.1.","triggerScenarios":"Calling ValidateBindAddr with an addr whose host is not parseable as an IP: 'localhost:8080', a hostname like 'myhost:8080', or malformed IP text like '127.0.0.999:8080'.","commonSituations":"Users habitually write 'localhost:PORT' in dev setups, copy a Kubernetes service DNS name into --addr, or typo an IPv4/IPv6 literal.","solutions":["Replace the name with a numeric IP literal, e.g. --addr 127.0.0.1:8080 instead of localhost:8080","Use ::1 or [::1]:PORT for IPv6 loopback","Resolve the hostname to an IP outside the tool if a remote bind is truly needed (then see --allow-non-loopback)"],"exampleFix":"// before\n--addr localhost:8080\n// after\n--addr 127.0.0.1:8080","handlingStrategy":"validation","validationCode":"func validIPHost(addr string) bool {\n    host, _, err := net.SplitHostPort(addr)\n    return err == nil && net.ParseIP(host) != nil\n}","typeGuard":null,"tryCatchPattern":"if ip, err := httpapi.ValidateBindAddr(addr, false); err != nil {\n    log.Fatalf(\"bad --addr: %v\", err)\n} else { _ = ip }","preventionTips":["Use 127.0.0.1 instead of localhost","Pre-validate host with net.ParseIP before invoking the server","Never paste hostnames or DNS names into --addr"],"tags":["validation","cli","network","address-parsing"],"backgroundTag":"invalid-bind-address","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}