{"record":{"id":"7e84420e3fdd7a7b","repo":"caddyserver/caddy","slug":"invalid-listener-address-s-v","errorCode":null,"errorMessage":"invalid listener address '%s': %v","messagePattern":"invalid listener address '(.+?)': (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/app.go","lineNumber":424,"sourceCode":"\t\t}\n\t\tif srv.ReadHeaderTimeout == 0 {\n\t\t\tsrv.ReadHeaderTimeout = defaultReadHeaderTimeout // see #6663\n\t\t}\n\t}\n\tctx.Context = oldContext\n\treturn nil\n}\n\n// Validate ensures the app's configuration is valid.\nfunc (app *App) Validate() error {\n\tlnAddrs := make(map[string]string)\n\n\tfor srvName, srv := range app.Servers {\n\t\t// each server must use distinct listener addresses\n\t\tfor _, addr := range srv.Listen {\n\t\t\tlistenAddr, err := caddy.ParseNetworkAddress(addr)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"invalid listener address '%s': %v\", addr, err)\n\t\t\t}\n\t\t\t// check that every address in the port range is unique to this server;\n\t\t\t// we do not use <= here because PortRangeSize() adds 1 to EndPort for us\n\t\t\tfor i := uint(0); i < listenAddr.PortRangeSize(); i++ {\n\t\t\t\taddr := caddy.JoinNetworkAddress(listenAddr.Network, listenAddr.Host, strconv.FormatUint(uint64(listenAddr.StartPort+i), 10))\n\t\t\t\tif sn, ok := lnAddrs[addr]; ok {\n\t\t\t\t\treturn fmt.Errorf(\"server %s: listener address repeated: %s (already claimed by server '%s')\", srvName, addr, sn)\n\t\t\t\t}\n\t\t\t\tlnAddrs[addr] = srvName\n\t\t\t}\n\t\t}\n\n\t\t// logger names must not have ports\n\t\tif srv.Logs != nil {\n\t\t\tfor host := range srv.Logs.LoggerNames {\n\t\t\t\tif _, _, err := net.SplitHostPort(host); err == nil {\n\t\t\t\t\treturn fmt.Errorf(\"server %s: logger name must not have a port: %s\", srvName, host)\n\t\t\t\t}","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/app.go#L406-L442","documentation":"App.Validate parses every address in servers.<name>.listen with caddy.ParseNetworkAddress. Addresses must be network/host/port combinations in a supported form (e.g. tcp/udp/unix, host:port, port ranges). An unparseable address fails validation before Caddy starts.","triggerScenarios":"A listen string missing a port (\"localhost\"), a bad port range (\"tcp/localhost:99999\"), an unknown network prefix, or stray characters like a trailing colon.","commonSituations":"Hand-edited JSON after adapting from a Caddyfile; forgetting that bare hosts without ports are invalid in the JSON listen array; copy-paste of URLs (scheme://) into listen.","solutions":["Use the form [network/]host:port with a valid port (0-65535 or a range like 8080-8090)","Drop any scheme (http://) from listen entries","Validate with `caddy validate` to confirm parsing"],"exampleFix":"// before\n\"listen\": [\"http://localhost:8080\"]\n// after\n\"listen\": [\"localhost:8080\"]","handlingStrategy":"validation","validationCode":"for _, a := range srvCfg.Listen {\n    if _, err := caddy.ParseNetworkAddress(a); err != nil {\n        return fmt.Errorf(\"listen %q: %w\", a, err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use caddy.ParseNetworkAddress (or `caddy validate`) as the single source of truth for address syntax","Never put schemes (http://) in listen entries; schemes belong in site addresses only","Prefer the Caddyfile adapter over hand-written JSON listen arrays"],"tags":["caddy","listener","validation","config"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}