{"record":{"id":"e7a8274325ce855a","repo":"caddyserver/caddy","slug":"finalizing-automatic-https-v","errorCode":null,"errorMessage":"finalizing automatic HTTPS: %v","messagePattern":"finalizing automatic HTTPS: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"modules/caddyhttp/app.go","lineNumber":670,"sourceCode":"\t\t\t\t\t\t// Can only serve h3 with TLS enabled\n\t\t\t\t\t\tapp.logger.Warn(\"HTTP/3 skipped because it requires TLS\",\n\t\t\t\t\t\t\tzap.String(\"network\", listenAddr.Network),\n\t\t\t\t\t\t\tzap.String(\"addr\", hostport))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrv.logger.Info(\"server running\",\n\t\t\tzap.String(\"name\", srvName),\n\t\t\tzap.Strings(\"protocols\", srv.Protocols))\n\t}\n\n\t// finish automatic HTTPS by finally beginning\n\t// certificate management\n\terr := app.automaticHTTPSPhase2()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"finalizing automatic HTTPS: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// stdlibLogPrefixPanic is the prefix Go's net/http server uses when it writes a\n// recovered handler panic (and its stack trace) to http.Server.ErrorLog.\n// See the deferred recover in net/http.(*conn).serve.\nconst stdlibLogPrefixPanic = \"http: panic serving\"\n\n// serverErrorLogger returns a *log.Logger suitable for http.Server.ErrorLog\n// that forwards the standard library's server messages to Caddy's structured\n// logger. Most of these messages are low-signal and logged at DEBUG, but\n// recovered handler panics indicate a real server-side error, so they are\n// logged at ERROR to stay visible at the default log level.\nfunc serverErrorLogger(logger *zap.Logger) *log.Logger {\n\treturn log.New(stdlibLogRouter{logger: logger}, \"\", 0)\n}","sourceCodeStart":652,"sourceCodeEnd":688,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/app.go#L652-L688","documentation":"After all servers are listening, automaticHTTPSPhase2 begins actual certificate management (issuing/renewing via ACME/Internal CAs, solving challenges, loading managed certs). Any failure in that startup — a CA rejecting issuance, challenge solver failure, cache errors — is wrapped as 'finalizing automatic HTTPS'. The server sockets are already open, but Caddy aborts Start.","triggerScenarios":"ACME account/issuance errors (e.g. Let's Encrypt rate limit, unreachable DNS), failing HTTP-01/TLS-ALPN challenges because ports 80/443 are not externally reachable, an explicitly configured internal CA that fails to initialize, or on-demand cert config errors.","commonSituations":"First deploy behind a firewall blocking port 80 so HTTP-01 fails; DNS for the domain not yet pointing at the server; staging->production LE quota exhaustion; test environments without internet access.","solutions":["Read the wrapped error to identify the failing CA/domain/challenge","For local/test use, force the internal CA: `tls internal` on that site so no external ACME is attempted","Open/forward ports 80+443 or switch to a DNS-01 challenge with a provider plugin; wait out rate limits or use Let's Encrypt staging while testing"],"exampleFix":"# before\nexample.com {\n  reverse_proxy localhost:8080\n}\n# after (local testing)\nexample.com {\n  tls internal\n  reverse_proxy localhost:8080\n}","handlingStrategy":"fallback","validationCode":"// pre-flight DNS check for ACME-managed domains\nfor _, d := range managedDomains {\n    addrs, err := net.LookupHost(d)\n    if err != nil || len(addrs) == 0 {\n        return fmt.Errorf(\"domain %s does not resolve; issuance will fail\", d)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := caddy.Run(cfg); err != nil {\n    if strings.Contains(err.Error(), \"finalizing automatic HTTPS\") {\n        // fallback: rerun with tls internal / ACME staging, or surface the wrapped cause\n    }\n}","preventionTips":["Point DNS at the server and open 80+443 before first start","Use Let's Encrypt staging (`acme_ca`) while testing to dodge rate limits","Use `tls internal` for anything not needing public trust; disable auto_https for pure HTTP backends"],"tags":["caddy","https","acme","tls","certificates","startup"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}