{"record":{"id":"af4d5654076c0178","repo":"caddyserver/caddy","slug":"server-s-listener-protocols-count-does-not-match","errorCode":null,"errorMessage":"server %s: listener protocols count does not match address count: %d != %d","messagePattern":"server (.+?): listener protocols count does not match address count: (.+?) != (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/app.go","lineNumber":258,"sourceCode":"\t\t\tapp.Metrics.PerHost = app.Metrics.PerHost || srv.Metrics.PerHost\n\t\t}\n\n\t\t// only enable access logs if configured\n\t\tif srv.Logs != nil {\n\t\t\tsrv.accessLogger = app.logger.Named(\"log.access\")\n\t\t\tif srv.Logs.Trace {\n\t\t\t\tsrv.traceLogger = app.logger.Named(\"log.trace\")\n\t\t\t}\n\t\t}\n\n\t\t// if no protocols configured explicitly, enable all except h2c\n\t\tif len(srv.Protocols) == 0 {\n\t\t\tsrv.Protocols = srv.protocolsWithDefaults()\n\t\t}\n\n\t\tif srv.ListenProtocols != nil {\n\t\t\tif len(srv.ListenProtocols) != len(srv.Listen) {\n\t\t\t\treturn fmt.Errorf(\"server %s: listener protocols count does not match address count: %d != %d\",\n\t\t\t\t\tsrvName, len(srv.ListenProtocols), len(srv.Listen))\n\t\t\t}\n\n\t\t\tfor i, lnProtocols := range srv.ListenProtocols {\n\t\t\t\tif lnProtocols != nil {\n\t\t\t\t\tsrv.ListenProtocols[i] = srv.listenerProtocolsWithDefaults(lnProtocols)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// limit max header bytes to a more reasonable default than 1MB from Go std lib\n\t\t// (see https://github.com/php/frankenphp/issues/2459#issuecomment-4655612909)\n\t\tif srv.MaxHeaderBytes <= 0 {\n\t\t\tsrv.MaxHeaderBytes = 16 * 1024\n\t\t}\n\n\t\t// if not explicitly configured by the user, disallow TLS\n\t\t// client auth bypass (domain fronting) which could","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/app.go#L240-L276","documentation":"Per-server validation in the http app: when listen_protocols is set, its slice length must equal the length of the listen addresses slice, because the two are index-paired. A mismatch aborts provisioning with both counts printed.","triggerScenarios":"server { listen [\":443\", \":80\"] listen_protocols [[\"h1\",\"h2\",\"h3\"]] } — 2 addresses but 1 protocols entry. Also triggered by JSON configs with mismatched arrays, or removing a listen address without updating protocols.","commonSituations":"Adding/removing a listen address and forgetting listen_protocols; hand-edited JSON; copy-paste between server blocks with different address counts.","solutions":["Make the arrays the same length: one protocols entry (possibly null for defaults) per listen address, in the same order.","Or drop listen_protocols entirely to use the default protocol set on all listeners.","Use null (JSON) / leave an empty entry for any listener that should keep defaults."],"exampleFix":"// before (caddyfile)\nsrv0 {\n    listen :443 :80\n    listen_protocols h1 h2 h3\n}\n\n// after\nsrv0 {\n    listen :443 :80\n    listen_protocols h1 h2 h3 h1 h2\n}","handlingStrategy":"validation","validationCode":"// before load: arrays must be index-paired\nif len(srv.ListenProtocols) != 0 && len(srv.ListenProtocols) != len(srv.Listen) {\n    return fmt.Errorf(\"listen_protocols has %d entries but listen has %d addresses\", len(srv.ListenProtocols), len(srv.Listen))\n}","typeGuard":null,"tryCatchPattern":"if err := caddy.Validate(cfg); err != nil {\n    if strings.Contains(err.Error(), \"listener protocols count does not match address count\") {\n        // align the two arrays (or drop listen_protocols) and re-validate\n    }\n    return err\n}","preventionTips":["Edit listen and listen_protocols together — they are positionally paired.","Omit listen_protocols when the default protocol set is acceptable everywhere.","Add a config lint rule that asserts equal lengths of the two arrays."],"tags":["http","listen","protocols","validation"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}