{"record":{"id":"a3bd4e8a1a15bc0c","repo":"caddyserver/caddy","slug":"decoding-root-key-v","errorCode":null,"errorMessage":"decoding root key: %v","messagePattern":"decoding root key: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"modules/caddypki/ca.go","lineNumber":311,"sourceCode":"\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()\n\n\trootCert, rootKey, err = generateRoot(repl.ReplaceAll(ca.RootCommonName, \"\"))\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"generating CA root: %v\", err)\n\t}\n\trootCertPEM, err := pemEncodeCert(rootCert.Raw)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"encoding root certificate: %v\", err)\n\t}\n\terr = ca.storage.Store(ca.ctx, ca.storageKeyRootCert(), rootCertPEM)","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddypki/ca.go#L293-L329","documentation":"The root key PEM was retrieved from storage but certmagic.PEMDecodePrivateKey could not decode it into a crypto.Signer. The bytes exist but are not a valid private-key PEM (wrong block type, unsupported algorithm, or corrupt base64), so the CA cannot use the root for signing.","triggerScenarios":"key.pem contains garbage, a certificate instead of a key, an encrypted/passphrase-protected key (certmagic cannot decrypt it), or a PEM header/type PEMDecodePrivateKey rejects (e.g. non-PEM DER dumped raw). Raised in loadOrGenRoot right after loading the key bytes.","commonSituations":"User replaced storage key.pem with an OpenSSL-generated encrypted key ('-----BEGIN ENCRYPTED PRIVATE KEY-----'); scripts writing DER or PKCS#1/PKCS#8 variants that decode fails on; truncation from a disk-full event.","solutions":["Replace the stored key with a valid unencrypted PEM private key that matches the stored root.crt (openssl pkey -in key.pem -noout to validate; remove -aes256 passphrases when exporting).","If the original key is gone, regenerate CA assets in storage and re-trust the new root.","Ensure the key matches the cert: compare openssl x509 -pubkey vs openssl pkey -pubout outputs.","Keep automated tooling from re-writing storage objects in place; write-and-rename instead."],"exampleFix":"# before: storage key.pem is encrypted\n-----BEGIN ENCRYPTED PRIVATE KEY-----...\n# after: unencrypted, matching the root cert\nopenssl pkey -in enc.key -out key.pem\n-----BEGIN PRIVATE KEY-----...","handlingStrategy":"validation","validationCode":"// Reject encrypted/mismatched keys before startup\nblock, _ := pem.Decode(keyPEM)\nif block == nil || strings.Contains(block.Type, \"ENCRYPTED\") { log.Fatal(\"key must be unencrypted PEM\") }","typeGuard":"func isUnencryptedPrivateKeyPEM(b []byte) bool {\n    block, _ := pem.Decode(b)\n    return block != nil && (block.Type == \"PRIVATE KEY\" || block.Type == \"EC PRIVATE KEY\" || block.Type == \"RSA PRIVATE KEY\")\n}","tryCatchPattern":"if strings.Contains(err.Error(), \"decoding root key\") {\n    // replace stored key with unencrypted PEM matching root.crt, or regenerate CA\n}","preventionTips":["When exporting keys with OpenSSL, omit passphrase flags (-aes*) for keys Caddy must read.","Validate key PEMs (openssl pkey -noout) as part of deployment checks.","Document that CA storage keys must remain in certmagic-compatible, unencrypted PEM."],"tags":["pki","root-key","pem","crypto"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}