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

  1. Use GET for /pki/ca/<id>
  2. To create or change a CA, edit the config (pki app in JSON / global options) and load it via the config admin endpoint instead
  3. 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

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


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