{"record":{"id":"df93dcbcf95036bf","repo":"caddyserver/caddy","slug":"server-s-listener-address-repeated-s-already","errorCode":null,"errorMessage":"server %s: listener address repeated: %s (already claimed by server '%s')","messagePattern":"server (.+?): listener address repeated: (.+?) \\(already claimed by server '(.+?)'\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/app.go","lineNumber":431,"sourceCode":"}\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}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc removeTLSALPN(srv *Server, target string) {","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/app.go#L413-L449","documentation":"App.Validate builds a set of all listener addresses (expanding port ranges) across servers and rejects duplicates. Each concrete network/host/port must be claimed by exactly one server, or config validation fails, naming both the offending and the earlier server.","triggerScenarios":"Two servers both listening on :443, overlapping port ranges (server A: 8080-8090, server B: 8085), or the same unix socket path in two servers. Since map iteration order varies, either server may be named first.","commonSituations":"Adding a second site block that gets its own server object with the same address; splitting HTTP/1-only and HTTP/3 servers but keeping identical listen addresses; port-range configs that accidentally overlap.","solutions":["Give each server distinct addresses/ports (or non-overlapping ranges)","If both should share an address, merge them into one server and route by host matcher","Check for overlapping port ranges when using ranges"],"exampleFix":"// before\nsrv1.listen=[\":443\"], srv2.listen=[\":443\"]\n// after\nsrv1.listen=[\":443\"] with host matchers for both sites","handlingStrategy":"validation","validationCode":"seen := map[string]string{}\nfor sn, s := range srvCfg.Servers {\n    for _, a := range s.Listen {\n        na, _ := caddy.ParseNetworkAddress(a)\n        for i := uint(0); i < na.PortRangeSize(); i++ {\n            key := caddy.JoinNetworkAddress(na.Network, na.Host, strconv.Itoa(int(na.StartPort+i)))\n            if prev, dup := seen[key]; dup {\n                return fmt.Errorf(\"%s duplicated by %s and %s\", key, prev, sn)\n            }\n            seen[key] = sn\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["One server per address; multiplex sites with host matchers","When using port ranges, double-check range overlaps across servers","Run `caddy validate` after every server split/merge refactor"],"tags":["caddy","listener","validation","ports","config"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}