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

  1. Check the wrapped inner error in the response body/logs — storage errors name the failing operation
  2. 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
  3. Test the storage backend connectivity/credentials if a custom storage module is configured
  4. 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

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


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/75fc0ea9a2442548. Report an issue: GitHub.