{"record":{"id":"a0a6bfd62784260c","repo":"caddyserver/caddy","slug":"s-scheme-and-port-violate-convention","errorCode":null,"errorMessage":"[%s] scheme and port violate convention","messagePattern":"\\[(.+?)\\] scheme and port violate convention","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/httpcaddyfile/addresses.go","lineNumber":306,"sourceCode":"\t\thttpPort = strconv.Itoa(hport.(int))\n\t}\n\tif hsport, ok := options[\"https_port\"]; ok {\n\t\thttpsPort = strconv.Itoa(hsport.(int))\n\t}\n\n\t// default port is the HTTPS port\n\tlnPort := httpsPort\n\tif addr.Port != \"\" {\n\t\t// port explicitly defined\n\t\tlnPort = addr.Port\n\t} else if addr.Scheme == \"http\" {\n\t\t// port inferred from scheme\n\t\tlnPort = httpPort\n\t}\n\n\t// error if scheme and port combination violate convention\n\tif (addr.Scheme == \"http\" && lnPort == httpsPort) || (addr.Scheme == \"https\" && lnPort == httpPort) {\n\t\treturn nil, fmt.Errorf(\"[%s] scheme and port violate convention\", addr.String())\n\t}\n\n\t// the bind directive specifies hosts (and potentially network), and the protocols to serve them with, but is optional\n\tlnCfgVals := make([]addressesWithProtocols, 0, len(sblock.pile[\"bind\"]))\n\tfor _, cfgVal := range sblock.pile[\"bind\"] {\n\t\tif val, ok := cfgVal.Value.(addressesWithProtocols); ok {\n\t\t\tlnCfgVals = append(lnCfgVals, val)\n\t\t}\n\t}\n\tif len(lnCfgVals) == 0 {\n\t\tif defaultBindValues, ok := options[\"default_bind\"].([]ConfigValue); ok {\n\t\t\tfor _, defaultBindValue := range defaultBindValues {\n\t\t\t\tlnCfgVals = append(lnCfgVals, defaultBindValue.Value.(addressesWithProtocols))\n\t\t\t}\n\t\t} else {\n\t\t\tlnCfgVals = []addressesWithProtocols{{\n\t\t\t\taddresses: []string{\"\"},\n\t\t\t\tprotocols: nil,","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/httpcaddyfile/addresses.go#L288-L324","documentation":"The resolved listener port contradicts the key's scheme: http:// on the HTTPS port, or https:// on the HTTP port (defaults 443/80, or the http_port/https_port globals). Caddy enforces the convention to catch config mistakes that would otherwise serve TLS on the wrong port silently.","triggerScenarios":"Keys like 'http://example.com:443' or 'https://example.com:80', or with globals http_port 443 / https_port 80 set, any http key without explicit port resolves to the https port and trips this.","commonSituations":"Running HTTP explicitly on 443 during testing, or swapping http_port/https_port globals to dodge a port conflict without updating site labels.","solutions":["Align scheme and port: use https with 443 (or your https_port) and http with 80 (or your http_port)","If you truly need HTTP on the HTTPS port, omit the scheme but keep the port, or re-map ports consistently in the globals","Check the global options block for http_port/https_port overrides that interact with the key"],"exampleFix":"# before\nhttp://example.com:443 {\n}\n# after\nhttps://example.com:443 {\n}","handlingStrategy":"validation","validationCode":"httpPort, httpsPort := \"80\", \"443\" // or your overrides\nport := addr.Port\nif port == \"\" { port = map[bool]string{true: httpPort, false: httpsPort}[addr.Scheme == \"http\"] }\nif (addr.Scheme == \"http\" && port == httpsPort) || (addr.Scheme == \"https\" && port == httpPort) {\n    return fmt.Errorf(\"%s mixes scheme and port\", addr.String())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep scheme/port pairs canonical: http=80/http_port, https=443/https_port","When overriding http_port/https_port globals, update all site labels consistently","Omit the port on site labels when using defaults"],"tags":["caddyfile","site-address","port","scheme","convention"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}