{"id":"045aabd313b0ca87","repo":"gohugoio/hugo","slug":"failed-to-verify-certificate-v","errorCode":null,"errorMessage":"failed to verify certificate: %v","messagePattern":"failed to verify certificate: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"commands/server.go","lineNumber":747,"sourceCode":"\t\treturn fmt.Errorf(\"failed to parse root certificate\")\n\t}\n\n\tblock, _ := pem.Decode(certPEM)\n\tif block == nil {\n\t\treturn fmt.Errorf(\"failed to parse certificate PEM\")\n\t}\n\tcert, err := x509.ParseCertificate(block.Bytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse certificate: %v\", err.Error())\n\t}\n\n\topts := x509.VerifyOptions{\n\t\tDNSName: name,\n\t\tRoots:   roots,\n\t}\n\n\tif _, err := cert.Verify(opts); err != nil {\n\t\treturn fmt.Errorf(\"failed to verify certificate: %v\", err.Error())\n\t}\n\n\treturn nil\n}\n\nfunc (c *serverCommand) createServerPorts(cd *simplecobra.Commandeer) error {\n\tflags := cd.CobraCommand.Flags()\n\tvar cerr error\n\tc.withConf(func(conf *commonConfig) {\n\t\tisMultihost := conf.configs.IsMultihost\n\t\tc.serverPorts = make([]serverPortListener, 1)\n\t\tif isMultihost {\n\t\t\tif !c.serverAppend {\n\t\t\t\tcerr = errors.New(\"--appendPort=false not supported when in multihost mode\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tc.serverPorts = make([]serverPortListener, len(conf.configs.Languages))\n\t\t}","sourceCodeStart":729,"sourceCodeEnd":765,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/commands/server.go#L729-L765","documentation":"The cached certificate parsed cleanly, but chain verification against the mkcert root CA failed for the requested hostname (`cert.Verify` with `DNSName` and the mkcert root pool). Hugo uses this check to decide whether a cached cert is still usable; failure typically means expiry, hostname mismatch, or a cert signed by a different (e.g. regenerated) mkcert root.","triggerScenarios":"`hugo server --tlsAuto` where the cached cert is expired, its SANs don't cover the hostname derived from `--baseURL` (default `localhost`), or the mkcert root CA was reinstalled/rotated since the cert was minted so the chain no longer terminates at the current `rootCA.pem`.","commonSituations":"Changing `--baseURL`/config baseURL to a new hostname while an old `localhost` cert is cached; mkcert reinstalled after an OS refresh, invalidating old leaf certs; long-lived dev machines where the cached cert expired.","solutions":["Delete `<hugo cacheDir>/_mkcerts/` so Hugo mints a fresh cert for the current hostname against the current mkcert root.","If you changed the site's baseURL hostname, expect a new cert to be generated — clear the stale one for the old name.","Re-run `mkcert -install` if the root CA was rotated, then regenerate.","Check expiry: `openssl x509 -in <host>.pem -noout -dates -ext subjectAltName`."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if _, err := cert.Verify(x509.VerifyOptions{Roots: pool, DNSName: host}); err != nil {\n    return fmt.Errorf(\"cert won't verify against provided CA: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"cert, err := server.Serve()\nif err != nil && strings.Contains(err.Error(), \"failed to verify certificate\") {\n    log.Fatal(\"TLS cert not signed by the given CA or expired — regenerate with mkcert/hugo server trust\")\n}","preventionTips":["Ensure the leaf cert was actually signed by the CA file you pass","Check certificate expiry (`openssl x509 -enddate`)","Confirm the cert's SANs cover the hostname hugo serves on"],"tags":["tls","certificate-verification","hugo-server","mkcert"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}