caddyserver/caddy · error
server %s: logger name must not have a port: %s
Error message
server %s: logger name must not have a port: %s
What it means
In App.Validate, every key of servers.<name>.logs.logger_names must be a host name without a port. Because net.SplitHostPort succeeds on strings like "example.com:8080", such keys are rejected — log customization is keyed by host, not address.
Source
Thrown at modules/caddyhttp/app.go:441
if err != nil {
return fmt.Errorf("invalid listener address '%s': %v", addr, err)
}
// check that every address in the port range is unique to this server;
// we do not use <= here because PortRangeSize() adds 1 to EndPort for us
for i := uint(0); i < listenAddr.PortRangeSize(); i++ {
addr := caddy.JoinNetworkAddress(listenAddr.Network, listenAddr.Host, strconv.FormatUint(uint64(listenAddr.StartPort+i), 10))
if sn, ok := lnAddrs[addr]; ok {
return fmt.Errorf("server %s: listener address repeated: %s (already claimed by server '%s')", srvName, addr, sn)
}
lnAddrs[addr] = srvName
}
}
// logger names must not have ports
if srv.Logs != nil {
for host := range srv.Logs.LoggerNames {
if _, _, err := net.SplitHostPort(host); err == nil {
return fmt.Errorf("server %s: logger name must not have a port: %s", srvName, host)
}
}
}
}
return nil
}
func removeTLSALPN(srv *Server, target string) {
for _, cp := range srv.TLSConnPolicies {
// the TLSConfig was already provisioned, so... manually remove it
for i, np := range cp.TLSConfig.NextProtos {
if np == target {
cp.TLSConfig.NextProtos = append(cp.TLSConfig.NextProtos[:i], cp.TLSConfig.NextProtos[i+1:]...)
break
}
}
// remove it from the parent connection policy too, just to keep things tidy
for i, alpn := range cp.ALPN {View on GitHub (pinned to 50e54ee279)
Solutions
- Strip the port: use just the host ("example.com") as the logger_names key
- If you need per-port logging, use separate servers and set per-server access logging instead
Example fix
// before
"logs":{"logger_names":{"example.com:443":"web"}}
// after
"logs":{"logger_names":{"example.com":"web"}} Defensive patterns
Strategy: validation
Validate before calling
for host := range srvCfg.Logs.LoggerNames {
if _, _, err := net.SplitHostPort(host); err == nil {
return fmt.Errorf("logger_names key %q must not contain a port", host)
}
} Prevention
- Generate logger_names keys from parsed hostnames, not from site address strings
- Remember logs are keyed by host only; per-port behavior requires separate servers
When it happens
Trigger: Writing a logger_names key that includes a port, e.g. {"example.com:443": "logname"}, typically when copying addresses from the listen array into the logs config.
Common situations: Adapting a Caddyfile where the site address includes a port and pasting it into the access_logs/logger_names JSON; multi-port setups where users assume logs are per-address.
Related errors
- parsing listener address: %v
- must be exactly one listener address; cannot listen on: %s
- indexing config: %v
- %s: %s field must be a string or number
- duplicate ID '%s' found at %s and %s
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/54e7d0cb23796e0b.
Report an issue: GitHub.