{"record":{"id":"75fc0ea9a2442548","repo":"caddyserver/caddy","slug":"failed-to-get-root-and-intermediate-cert-for-ca-s","errorCode":null,"errorMessage":"failed to get root and intermediate cert for CA %s: %v","messagePattern":"failed to get root and intermediate cert for CA (.+?): (.+?)","errorType":"http","errorClass":"caddy.APIError","httpStatus":500,"severity":"error","filePath":"modules/caddypki/adminapi.go","lineNumber":111,"sourceCode":"// error if they have not been previously provisioned.\nfunc (a *adminAPI) handleCAInfo(w http.ResponseWriter, r *http.Request) error {\n\tif r.Method != http.MethodGet {\n\t\treturn caddy.APIError{\n\t\t\tHTTPStatus: http.StatusMethodNotAllowed,\n\t\t\tErr:        fmt.Errorf(\"method not allowed: %v\", r.Method),\n\t\t}\n\t}\n\n\tca, err := a.getCAFromAPIRequestPath(r)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\trootCert, interCert, err := rootAndIntermediatePEM(ca)\n\tif err != nil {\n\t\treturn caddy.APIError{\n\t\t\tHTTPStatus: http.StatusInternalServerError,\n\t\t\tErr:        fmt.Errorf(\"failed to get root and intermediate cert for CA %s: %v\", ca.ID, err),\n\t\t}\n\t}\n\n\trepl := ca.newReplacer()\n\n\tresponse := caInfo{\n\t\tID:               ca.ID,\n\t\tName:             ca.Name,\n\t\tRootCN:           repl.ReplaceAll(ca.RootCommonName, \"\"),\n\t\tIntermediateCN:   repl.ReplaceAll(ca.IntermediateCommonName, \"\"),\n\t\tRootCert:         string(rootCert),\n\t\tIntermediateCert: string(interCert),\n\t}\n\n\tencoded, err := json.Marshal(response)\n\tif err != nil {\n\t\treturn caddy.APIError{\n\t\t\tHTTPStatus: http.StatusInternalServerError,","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddypki/adminapi.go#L93-L129","documentation":"A 500 caddy.APIError from handleCAInfo when rootAndIntermediatePEM(ca) fails to PEM-encode the CA's root or intermediate certificate (pemEncodeCert of ca.RootCertificate().Raw). This means the CA object exists but its root certificate could not be materialized — typically storage could not load/generate the root, or the certificate bytes are unreadable. The CA id is included in the message.","triggerScenarios":"GET /pki/ca/&lt;id&gt; where the CA's storage backend fails to read the root cert (e.g. a broken/unreachable custom storage module, corrupted cert resource, permission loss on the storage keys), or RootCertificate() returns a nil/empty cert after a partial provisioning. The inner error from pemEncodeCert is wrapped with %v.","commonSituations":"Custom storage (e.g. redis/s3 module) misconfigured after a config change, so cert resources can't be fetched; root key present in storage but root cert resource deleted; a CA that was provisioned by an older Caddy version with an incompatible resource layout; expired storage credentials.","solutions":["Check the wrapped inner error in the response body/logs — storage errors name the failing operation","Verify storage integrity: with default file storage, inspect the pki/ directories under Caddy's storage root; ensure the root cert and key files exist and are readable","Test the storage backend connectivity/credentials if a custom storage module is configured","As a last resort for an expendable local CA, remove its storage resources and let Caddy regenerate (clients trusting the old root must re-trust)"],"exampleFix":"# before: custom storage unreachable\n# storage clean_interval ... (module config broken)\n\n# after: verify + fix storage, then\nsystemctl restart caddy\ncurl http://localhost:2019/pki/ca/local   # now returns PEMs","handlingStrategy":"try-catch","validationCode":"// Check CA material is present before relying on the endpoint:\ninfo, err := fetchJSON(base + \"/pki/ca/\" + id)\nif err != nil || info.RootCert == \"\" {\n    return fmt.Errorf(\"CA %s has no usable root cert: %v\", id, err)\n}","typeGuard":null,"tryCatchPattern":"// Inspect status + body together; 500 here means storage, not the request:\nresp, err := http.Get(url)\nif err != nil { return err }\nbody, _ := io.ReadAll(resp.Body)\nif resp.StatusCode >= 500 {\n    return fmt.Errorf(\"CA cert unavailable (server-side storage issue): %s\", body)\n}","preventionTips":["Monitor storage backend health (custom storage modules especially)","Keep backups of the pki storage resources (root/intermediate keys and certs)","Alert on 5xx from the PKI admin endpoints as a storage symptom"],"tags":["pki","admin-api","http-500","storage","certificates"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}