{"record":{"id":"b40ce2241afe54a3","repo":"caddyserver/caddy","slug":"automation-policy-from-site-block-is-also-default","errorCode":null,"errorMessage":"automation policy from site block is also default/catch-all policy because of key without hostname, and the two are in conflict: %#v != %#v","messagePattern":"automation policy from site block is also default/catch-all policy because of key without hostname, and the two are in conflict: %#v != %#v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/httpcaddyfile/tlsapp.go","lineNumber":172,"sourceCode":"\t\t\t\tvar issuers []certmagic.Issuer\n\t\t\t\tfor _, issuerVal := range issuerVals {\n\t\t\t\t\tissuers = append(issuers, issuerVal.Value.(certmagic.Issuer))\n\t\t\t\t}\n\t\t\t\tif ap == catchAllAP && !reflect.DeepEqual(ap.Issuers, issuers) {\n\t\t\t\t\t// this more correctly implements an error check that was removed\n\t\t\t\t\t// below; try it with this config:\n\t\t\t\t\t//\n\t\t\t\t\t// :443 {\n\t\t\t\t\t// \tbind 127.0.0.1\n\t\t\t\t\t// }\n\t\t\t\t\t//\n\t\t\t\t\t// :443 {\n\t\t\t\t\t// \tbind ::1\n\t\t\t\t\t// \ttls {\n\t\t\t\t\t// \t\tissuer acme\n\t\t\t\t\t// \t}\n\t\t\t\t\t// }\n\t\t\t\t\treturn nil, warnings, fmt.Errorf(\"automation policy from site block is also default/catch-all policy because of key without hostname, and the two are in conflict: %#v != %#v\", ap.Issuers, issuers)\n\t\t\t\t}\n\t\t\t\tap.Issuers = issuers\n\t\t\t}\n\n\t\t\t// certificate managers\n\t\t\tif certManagerVals, ok := sblock.pile[\"tls.cert_manager\"]; ok {\n\t\t\t\tfor _, certManager := range certManagerVals {\n\t\t\t\t\tcertGetterName := certManager.Value.(caddy.Module).CaddyModule().ID.Name()\n\t\t\t\t\tap.ManagersRaw = append(ap.ManagersRaw, caddyconfig.JSONModuleObject(certManager.Value, \"via\", certGetterName, &warnings))\n\t\t\t\t}\n\t\t\t}\n\t\t\t// custom bind host\n\t\t\tfor _, cfgVal := range sblock.pile[\"bind\"] {\n\t\t\t\tfor _, iss := range ap.Issuers {\n\t\t\t\t\t// if an issuer was already configured and it is NOT an ACME issuer,\n\t\t\t\t\t// skip, since we intend to adjust only ACME issuers; ensure we\n\t\t\t\t\t// include any issuer that embeds/wraps an underlying ACME issuer\n\t\t\t\t\tvar acmeIssuer *caddytls.ACMEIssuer","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/httpcaddyfile/tlsapp.go#L154-L190","documentation":"When a site block's address has no hostname (e.g. ':443'), its automation policy doubles as the catch-all policy for all sites. If another such site block already established a different issuer list (ap.Issuers vs issuers), the two catch-all policies conflict and adaptation aborts rather than silently picking one. The source comment shows the canonical repro: two ':443' blocks, one with 'tls { issuer acme }' and one without.","triggerScenarios":"Two site blocks keyed by hostname-less addresses (':443', 'https://:443') where global issuers were captured first and the second block's site-level tls issuers differ — e.g. one block sets 'tls { issuer acme }' (or internal) and the other leaves defaults.","commonSituations":"Splitting a config into ':443' blocks bound to different interfaces with distinct TLS settings; adding a new catch-all site with different issuer config next to an existing one.","solutions":["Give at least one block a hostname so its policy is no longer catch-all (e.g. 'example.com:443 { ... }'), as the source comment implies.","Make the issuer configuration identical across the conflicting catch-all blocks, or move issuer config to one place only.","Use distinct ports for the two catch-all sites so they do not merge into one policy scope."],"exampleFix":"# before\n:443 {\n  bind 127.0.0.1\n}\n:443 {\n  bind ::1\n  tls {\n    issuer acme\n  }\n}\n\n# after\nlocalhost:443 {\n  bind 127.0.0.1\n}\n[::1]:443 {\n  bind ::1\n  tls {\n    issuer acme\n  }\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid multiple hostname-less (catch-all) site blocks with differing tls settings.","Put catch-all TLS issuer configuration in one place only (global or one block).","Validate with 'caddy validate' before reload."],"tags":["caddyfile","tls","automation-policy","site-block"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}