{"record":{"id":"85a612fb266c1fcd","repo":"caddyserver/caddy","slug":"parsing-root-certificate-pem-v","errorCode":null,"errorMessage":"parsing root certificate PEM: %v","messagePattern":"parsing root certificate PEM: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"modules/caddypki/ca.go","lineNumber":301,"sourceCode":"\t\treturn rootChain[0], rootSigner, nil\n\t}\n\trootCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyRootCert())\n\tif err != nil {\n\t\tif !errors.Is(err, fs.ErrNotExist) {\n\t\t\treturn nil, nil, fmt.Errorf(\"loading root cert: %v\", err)\n\t\t}\n\n\t\t// TODO: should we require that all or none of the assets are required before overwriting anything?\n\t\trootCert, rootKey, err = ca.genRoot()\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"generating root: %v\", err)\n\t\t}\n\t}\n\n\tif rootCert == nil {\n\t\trootCert, err = pemDecodeCertificate(rootCertPEM)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"parsing root certificate PEM: %v\", err)\n\t\t}\n\t}\n\tif rootKey == nil {\n\t\trootKeyPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyRootKey())\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"loading root key: %v\", err)\n\t\t}\n\t\trootKey, err = certmagic.PEMDecodePrivateKey(rootKeyPEM)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"decoding root key: %v\", err)\n\t\t}\n\t}\n\n\treturn rootCert, rootKey, nil\n}\n\nfunc (ca CA) genRoot() (rootCert *x509.Certificate, rootKey crypto.Signer, err error) {\n\trepl := ca.newReplacer()","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddypki/ca.go#L283-L319","documentation":"A root certificate PEM was loaded from storage (so storage is healthy) but pemDecodeCertificate could not parse it into an x509.Certificate. This means the stored root.crt bytes are not a valid PEM CERTIFICATE block or not a parseable certificate — i.e. the asset is corrupt or was overwritten with different content.","triggerScenarios":"storage.Load returns bytes that fail pem/x509 parsing: truncated file, PEM block of the wrong type (e.g. a key stored in root.crt), base64 corruption, or a text editor inserting CRLF/BOM. Occurs on any CA load where the root already exists (second start, reload, new authority for an internal issuer).","commonSituations":"Manual edits to storage/caddy/pki/<id>/ca/root.crt; failed writes (disk full during a previous store); scripts copying the wrong file over root.crt; storage replication that mangled the object.","solutions":["Inspect the stored root cert (openssl x509 -in root.crt -noout) to confirm corruption; then restore a known-good copy or delete the CA directory in storage so Caddy regenerates root+intermediate.","If regenerated, re-install trust: caddy untrust && caddy trust (or redistribute the new root to clients) and restart clients relying on old certs.","Check disk space/storage health so Store() cannot half-write assets again.","Avoid hand-editing storage; mount storage read-only to humans if unintended edits recur."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate stored root before Caddy starts (cron/pre-start hook)\npem, err := os.ReadFile(rootCertPath)\nif err == nil {\n    if _, err := pemDecodeOneCert(pem); err != nil {\n        log.Fatalf(\"stored root cert corrupt: %v\", err)\n    }\n}","typeGuard":"func isParseableCertPEM(pemBytes []byte) bool {\n    block, _ := pem.Decode(pemBytes)\n    if block == nil || block.Type != \"CERTIFICATE\" { return false }\n    _, err := x509.ParseCertificate(block.Bytes)\n    return err == nil\n}","tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"parsing root certificate PEM\") {\n        // quarantine CA dir, restore backup or allow regeneration, restart\n    }\n    return err\n}","preventionTips":["Never hand-edit files under Caddy's storage directory; use export/import APIs.","Checksum and verify storage after restores or migrations.","Monitor disk space so writes cannot truncate PEM assets."],"tags":["pki","root-cert","pem","corruption"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}