{"record":{"id":"01414076428f7c5d","repo":"caddyserver/caddy","slug":"loading-root-key-v","errorCode":null,"errorMessage":"loading root key: %v","messagePattern":"loading root key: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"modules/caddypki/ca.go","lineNumber":307,"sourceCode":"\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()\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)","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddypki/ca.go#L289-L325","documentation":"After successfully loading a root cert from storage, Caddy loads the root's private key (storageKeyRootKey, e.g. key.pem). Any storage error here — the file/block is missing in a way not surfaced as fs.ErrNotExist handling for this branch, or the backend fails — is wrapped as 'loading root key'. Without the key the root cannot sign a new intermediate.","triggerScenarios":"storage.Load for the root key returns an error: the key object was deleted while the cert remains (partial state), permission/ownership mismatch on key.pem, or a custom storage backend error. Happens during loadOrGenRoot after the cert loaded fine.","commonSituations":"Someone removed key.pem 'for security' leaving root.crt; backup/restore that skipped dot/PEM key files; storage backend partial outage returning errors for one object; multi-node setups with inconsistent replicated storage.","solutions":["Restore the root key object at the expected storage key (pair it with the existing root.crt), e.g. copy key.pem back to storage/caddy/pki/<id>/ca/.","If the key is lost, the root is unusable: delete that CA's storage assets and let Caddy generate a new root+intermediate, then redistribute trust (caddy trust) and reissue leaf certs (they are typically short-lived).","Fix permissions on the storage directory so the process can read both CA files.","For multi-instance deployments, verify all nodes see the same, complete storage contents."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-start integrity check: cert present => key must be present too\n_, certErr := os.Stat(caDir + \"/root.crt\")\n_, keyErr := os.Stat(caDir + \"/key.pem\")\nif certErr == nil && keyErr != nil { log.Fatal(\"partial CA state: root cert without key\") }","typeGuard":"func caAssetsComplete(dir string) bool {\n    for _, f := range []string{\"root.crt\", \"key.pem\"} {\n        if _, err := os.Stat(filepath.Join(dir, f)); err != nil { return false }\n    }\n    return true\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"loading root key\") {\n    // decide: restore key from backup, or wipe CA dir to regenerate + re-trust\n}\nreturn err","preventionTips":["Back up CA assets as an all-or-none set.","Exclude CA storage from ad-hoc security cleanup scripts that delete key files.","After any restore, run an asset-completeness check before starting Caddy."],"tags":["pki","root-key","storage","partial-state"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}