caddyserver/caddy · error · caddy.APIError
failed to get root and intermediate cert for CA %s: %v
Error message
failed to get root and intermediate cert for CA %s: %v
What it means
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.
Source
Thrown at modules/caddypki/adminapi.go:111
// error if they have not been previously provisioned.
func (a *adminAPI) handleCAInfo(w http.ResponseWriter, r *http.Request) error {
if r.Method != http.MethodGet {
return caddy.APIError{
HTTPStatus: http.StatusMethodNotAllowed,
Err: fmt.Errorf("method not allowed: %v", r.Method),
}
}
ca, err := a.getCAFromAPIRequestPath(r)
if err != nil {
return err
}
rootCert, interCert, err := rootAndIntermediatePEM(ca)
if err != nil {
return caddy.APIError{
HTTPStatus: http.StatusInternalServerError,
Err: fmt.Errorf("failed to get root and intermediate cert for CA %s: %v", ca.ID, err),
}
}
repl := ca.newReplacer()
response := caInfo{
ID: ca.ID,
Name: ca.Name,
RootCN: repl.ReplaceAll(ca.RootCommonName, ""),
IntermediateCN: repl.ReplaceAll(ca.IntermediateCommonName, ""),
RootCert: string(rootCert),
IntermediateCert: string(interCert),
}
encoded, err := json.Marshal(response)
if err != nil {
return caddy.APIError{
HTTPStatus: http.StatusInternalServerError,View on GitHub (pinned to 50e54ee279)
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)
Example fix
# before: custom storage unreachable # storage clean_interval ... (module config broken) # after: verify + fix storage, then systemctl restart caddy curl http://localhost:2019/pki/ca/local # now returns PEMs
Defensive patterns
Strategy: try-catch
Validate before calling
// Check CA material is present before relying on the endpoint:
info, err := fetchJSON(base + "/pki/ca/" + id)
if err != nil || info.RootCert == "" {
return fmt.Errorf("CA %s has no usable root cert: %v", id, err)
} Try / catch
// Inspect status + body together; 500 here means storage, not the request:
resp, err := http.Get(url)
if err != nil { return err }
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode >= 500 {
return fmt.Errorf("CA cert unavailable (server-side storage issue): %s", body)
} Prevention
- 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
When it happens
Trigger: GET /pki/ca/<id> 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.
Common situations: 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.
Related errors
- failed to provision CA %s, %w
- access control %d public key %d: parsing base64 certificate
- certificate lifetime (%s) should be less than intermediate c
- resource not found: %v
- method not allowed: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/75fc0ea9a2442548.
Report an issue: GitHub.