caddyserver/caddy · info · caddy.APIError
no certificate authority configured with id: %s
Error message
no certificate authority configured with id: %s
What it means
A 404 caddy.APIError returned when the requested CA id is not configured in the running pki app and is not the default id (`local`). The admin API refuses to conjure arbitrary CAs on demand; only the default CA gets lazily provisioned. The message includes the exact id that was not found.
Source
Thrown at modules/caddypki/adminapi.go:201
// Find the CA by ID, if PKI is configured
var ca *CA
var ok bool
if a.pkiApp != nil {
ca, ok = a.pkiApp.CAs[id]
}
// If we didn't find the CA, and PKI is not configured
// then we'll either error out if the CA ID is not the
// default. If the CA ID is the default, then we'll
// provision it, because the user probably aims to
// change their config to enable PKI immediately after
// if they actually requested the local CA ID.
if !ok {
if id != DefaultCAID {
return nil, caddy.APIError{
HTTPStatus: http.StatusNotFound,
Err: fmt.Errorf("no certificate authority configured with id: %s", id),
}
}
// Provision the default CA, which generates and stores a root
// certificate in storage, if one doesn't already exist.
ca = new(CA)
err := ca.Provision(a.ctx, id, a.log)
if err != nil {
return nil, caddy.APIError{
HTTPStatus: http.StatusInternalServerError,
Err: fmt.Errorf("failed to provision CA %s, %w", id, err),
}
}
}
return ca, nil
}
View on GitHub (pinned to 50e54ee279)
Solutions
- List configured CAs: GET /pki/ca only routes known ids — inspect the running config via GET /config/ to see pki.certificate_authorities keys
- Add the CA to config (pki app, certificate_authorities.<id>) and reload, then retry
- Use the default id `local`, which provisions on demand
- Fix the id typo — ids are case-sensitive
Example fix
# before: 'myca' not in config
curl http://localhost:2019/pki/ca/myca # 404
# after: declare it, then query
cat caddy.json # "pki": {"certificate_authorities": {"myca": {}}}
curl -X PUT http://localhost:2019/load -H 'Content-Type: application/json' -d @caddy.json
curl http://localhost:2019/pki/ca/myca Defensive patterns
Strategy: validation
Validate before calling
// Compare requested id against configured CAs before calling:
func caExists(base, id string) bool {
resp, err := http.Get(base + "/config/pki/certificate_authorities")
if err != nil { return false }
defer resp.Body.Close()
var m map[string]json.RawMessage
json.NewDecoder(resp.Body).Decode(&m)
_, ok := m[id]
return ok || id == "local"
} Type guard
func isKnownCA(id string, configured map[string]bool) bool {
return configured[id] || id == "local"
} Try / catch
// 404 here is a config gap, not transient — do not retry:
if resp.StatusCode == 404 {
return fmt.Errorf("CA %q not configured; add it under pki.certificate_authorities", id)
} Prevention
- Declare every CA you intend to query under pki.certificate_authorities
- Remember only `local` auto-provisions via the admin API
- CA ids are case-sensitive; use them verbatim from config
When it happens
Trigger: GET /pki/ca/myca when the config's pki.certificate_authorities has no `myca` entry (or the pki app isn't configured at all). The lookup a.pkiApp.CAs[id] misses, id != DefaultCAID, and the 404 is returned.
Common situations: Querying a CA id defined in a different environment; typo in the id; the pki app config section was renamed/removed during a refactor; acme_server referencing a custom CA that isn't declared under pki.certificate_authorities.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- [%s] key does not exist: %s
- resource not found: %v
- unknown object ID '%s'
- decoding request body: %w, at offset %d
- decoding request body: %w
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/0b203ecced93965b.
Report an issue: GitHub.