{"id":"306a019b78fe59f6","repo":"gohugoio/hugo","slug":"failed-to-parse-root-certificate","errorCode":null,"errorMessage":"failed to parse root certificate","messagePattern":"failed to parse root certificate","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"commands/server.go","lineNumber":729,"sourceCode":"\t\t\tif err := c.verifyCert(rootPem, certPEM, hostname); err == nil {\n\t\t\t\tc.r.Println(\"Using existing\", c.tlsCertFile, \"and\", c.tlsKeyFile)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\n\tc.r.Println(\"Creating TLS certificates in\", keyDir)\n\n\t// Yes, this is unfortunate, but it's currently the only way to use Mkcert as a library.\n\tos.Args = []string{\"-cert-file\", c.tlsCertFile, \"-key-file\", c.tlsKeyFile, hostname}\n\treturn mclib.RunMain()\n}\n\nfunc (c *serverCommand) verifyCert(rootPEM, certPEM []byte, name string) error {\n\troots := x509.NewCertPool()\n\tok := roots.AppendCertsFromPEM(rootPEM)\n\tif !ok {\n\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())","sourceCodeStart":711,"sourceCodeEnd":747,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/commands/server.go#L711-L747","documentation":"With `--tlsAuto`, Hugo reuses mkcert-generated certificates cached under Hugo's cache dir, but first verifies the cached cert against the mkcert root CA (`$CAROOT/rootCA.pem`). This error means `x509.NewCertPool().AppendCertsFromPEM` found no valid certificate in that root file — the mkcert root CA PEM is corrupt or not actually PEM.","triggerScenarios":"`hugo server --tlsAuto` when `<CAROOT>/rootCA.pem` exists but contains no parsable PEM certificate blocks (truncated file, wrong encoding such as DER, empty file, or unrelated content).","commonSituations":"A corrupted or half-written mkcert install; `CAROOT` env pointing at the wrong directory; restoring dotfiles/backups that mangled `rootCA.pem`; converting the root cert to DER or replacing it manually.","solutions":["Regenerate the mkcert root: run `mkcert -install` (or delete the CAROOT dir and rerun) to recreate a valid `rootCA.pem`.","Check the `CAROOT` environment variable points at the directory that actually holds `rootCA.pem`.","Inspect the file: `openssl x509 -in \"$(mkcert -CAROOT)/rootCA.pem\" -noout -text` should succeed; if not, replace it.","Delete Hugo's cached certs (`<cacheDir>/_mkcerts`) so they are recreated after fixing the root."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"pem, err := os.ReadFile(caFile)\nif err != nil { return err }\npool := x509.NewCertPool()\nif !pool.AppendCertsFromPEM(pem) {\n    return errors.New(\"CA file contains no valid PEM certificates\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify the CA file with `openssl x509 -in ca.pem -noout -text` before use","Regenerate certs with `hugo server trust` / mkcert rather than hand-editing PEM files","Check the file isn't empty or a private key by mistake"],"tags":["tls","mkcert","hugo-server","certificates"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}