{"record":{"id":"5854716253f1d30e","repo":"caddyserver/caddy","slug":"global-options-are-ambiguous-local-certs-is-confu","errorCode":null,"errorMessage":"global options are ambiguous: local_certs is confusing when combined with cert_issuer, because local_certs is also a specific kind of issuer","messagePattern":"global options are ambiguous: local_certs is confusing when combined with cert_issuer, because local_certs is also a specific kind of issuer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/httpcaddyfile/tlsapp.go","lineNumber":937,"sourceCode":"\tglobalPreferredChains := options[\"preferred_chains\"]\n\thasGlobalACMEDefaults := globalACMECA != nil || globalACMECARoot != nil || globalACMEDNS || globalACMEEAB != nil || globalPreferredChains != nil\n\n\t// if there are no global options related to automation policies\n\t// set, then we can just return right away\n\tif !hasGlobalAutomationOpts && !hasGlobalACMEDefaults {\n\t\tif always {\n\t\t\treturn new(caddytls.AutomationPolicy), nil\n\t\t}\n\t\treturn nil, nil\n\t}\n\n\tap := new(caddytls.AutomationPolicy)\n\tif hasKeyType {\n\t\tap.KeyType = keyType.(string)\n\t}\n\n\tif hasIssuers && hasLocalCerts {\n\t\treturn nil, fmt.Errorf(\"global options are ambiguous: local_certs is confusing when combined with cert_issuer, because local_certs is also a specific kind of issuer\")\n\t}\n\n\tif hasIssuers {\n\t\tap.Issuers = issuers.([]certmagic.Issuer)\n\t} else if hasLocalCerts {\n\t\tap.Issuers = []certmagic.Issuer{new(caddytls.InternalIssuer)}\n\t}\n\n\tif hasGlobalACMEDefaults {\n\t\tfor i := range ap.Issuers {\n\t\t\tif err := fillInGlobalACMEDefaults(ap.Issuers[i], options); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"filling in global issuer defaults for issuer %d: %v\", i, err)\n\t\t\t}\n\t\t}\n\t}\n\n\tif hasOCSPStapling {\n\t\tocspConfig := ocspStapling.(certmagic.OCSPConfig)","sourceCodeStart":919,"sourceCodeEnd":955,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/httpcaddyfile/tlsapp.go#L919-L955","documentation":"newBaseAutomationPolicyFromDefaults rejects the global options combination of issuers (from 'cert_issuer', possibly multiple) together with 'local_certs'. local_certs is itself sugar for the internal issuer, so specifying both makes the intended issuer list ambiguous; the adapter refuses to guess.","triggerScenarios":"A global options block containing both 'local_certs' and 'cert_issuer <module> ...' (e.g. cert_issuer acme).","commonSituations":"Migrating a config from self-signed internal certs to ACME and leaving local_certs behind; copy-pasting a cert_issuer block into a template that already had local_certs.","solutions":["Remove 'local_certs' if you want the explicit cert_issuer to apply.","Or remove 'cert_issuer' if you want internal self-signed certs everywhere.","To mix internal and public per site, drop both globals and use per-site 'tls internal' / 'tls issuer acme'."],"exampleFix":"# before\n{\n  local_certs\n  cert_issuer acme\n}\n\n# after\n{\n  cert_issuer acme\n}","handlingStrategy":"validation","validationCode":"grep -nE 'local_certs|cert_issuer' Caddyfile  # both present => ambiguity","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Choose one TLS issuance strategy globally; use per-site tls blocks for exceptions."],"tags":["caddyfile","tls","global-options","ambiguous-config"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}