caddyserver/caddy · info · caddy.APIError
method not allowed: %v
Error message
method not allowed: %v
What it means
A 405 caddy.APIError returned by the PKI admin API's handleCAInfo when the request method is not GET. The /pki/ca/<id> endpoint is read-only: it returns CA metadata (id, name, common names, PEM certs), so POST/PUT/DELETE are rejected before any CA lookup happens. The error names the offending method.
Source
Thrown at modules/caddypki/adminapi.go:98
return a.handleCAInfo(w, r)
case len(parts) == 3 && parts[0] == "ca" && parts[1] != "" && parts[2] == "certificates":
return a.handleCACerts(w, r)
}
return caddy.APIError{
HTTPStatus: http.StatusNotFound,
Err: fmt.Errorf("resource not found: %v", r.URL.Path),
}
}
// handleCAInfo returns information about a particular
// CA by its ID. If the CA ID is the default, then the CA will be
// provisioned if it has not already been. Other CA IDs will return an
// 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()
View on GitHub (pinned to 50e54ee279)
Solutions
- Use GET for /pki/ca/<id>
- To create or change a CA, edit the config (pki app in JSON / global options) and load it via the config admin endpoint instead
- Check the response's Allow semantics: only GET is meaningful on this route
Example fix
# before
curl -X POST http://localhost:2019/pki/ca/local -d '{...}'
# after
curl http://localhost:2019/pki/ca/local
# to change the CA, load new config instead:
curl -X PUT http://localhost:2019/load -H 'Content-Type: application/json' -d @caddy.json Defensive patterns
Strategy: validation
Validate before calling
// Always issue GETs for CA info: req, _ := http.NewRequest(http.MethodGet, base+"/pki/ca/"+id, nil) // never POST/PUT/DELETE on this route
Try / catch
// Map 405 to a usage error in clients:
if resp.StatusCode == http.StatusMethodNotAllowed {
return errors.New("PKI CA endpoints are read-only; use GET")
} Prevention
- Remember the PKI admin API is read-only for CA info
- Use the /load endpoint to change CA configuration, not /pki/*
- Default http clients to explicit methods, not verbs inherited from templates
When it happens
Trigger: Sending POST/PUT/DELETE/PATCH to /pki/ca/<id> — for example a script trying to create or reconfigure a CA via the admin API. The method check is the first statement in the handler, so even a valid CA id returns 405 when the method is wrong.
Common situations: Assuming the admin API can create CAs (it cannot — CA creation is config-driven only); REST tooling defaulting to POST; retrying a GET with POST after a transient failure.
Related errors
- resource not found: %v
- failed to get root and intermediate cert for CA %s: %v
- missing CA in path
- no certificate authority configured with id: %s
- failed to provision CA %s, %w
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/5363fb2529cde872.
Report an issue: GitHub.