cloudflare/cloudflared · error
API errors: %s
Error message
API errors: %s
What it means
cfapi/base_client.go's (*response).checkErrors converts the errors array of a Cloudflare API response envelope into a Go error. When the envelope contains exactly one error it returns that structured apiError; when there are multiple, it concatenates all their messages with "; " separators into a single "API errors: ..." error. This surfaces validation/rejection details returned by the Cloudflare API for a failed request.
Source
Thrown at cfapi/base_client.go:209
type Pagination struct {
Count int `json:"count,omitempty"`
Page int `json:"page,omitempty"`
PerPage int `json:"per_page,omitempty"`
TotalCount int `json:"total_count,omitempty"`
}
func (r *response) checkErrors() error {
if len(r.Errors) == 0 {
return nil
}
if len(r.Errors) == 1 {
return r.Errors[0]
}
var messagesBuilder strings.Builder
for _, e := range r.Errors {
messagesBuilder.WriteString(fmt.Sprintf("%s; ", e))
}
return fmt.Errorf("API errors: %s", messagesBuilder.String())
}
type apiError struct {
Code json.Number `json:"code,omitempty"`
Message string `json:"message,omitempty"`
}
func (e apiError) Error() string {
return fmt.Sprintf("code: %v, reason: %s", e.Code, e.Message)
}
func (r *RESTClient) statusCodeToError(op string, resp *http.Response) error {
if resp.Header.Get("Content-Type") == "application/json" {
var errorsResp response
if json.NewDecoder(resp.Body).Decode(&errorsResp) == nil {
if err := errorsResp.checkErrors(); err != nil {
return errors.Errorf("Failed to %s: %s", op, err)
}View on GitHub (pinned to 2253eeeb25)
Solutions
- Parse the joined message — each ';'-separated entry is one API error; fix the reported fields/IDs and retry.
- Inspect HTTP status and the structured apiError (Code/Message) via statusCodeToError for the primary cause.
- Validate request payloads (zone IDs, record names, TTLs) against Cloudflare API docs before sending.
- Check API token permissions/scopes if messages indicate authentication/authorization failures.
- Apply backoff and retry if errors indicate transient rate limiting (error code 9xx/rate limit headers).
Example fix
// before: log-and-continue on envelope errors
resp, _ := client.ZoneDetails(ctx, zoneID)
// after: surface compound API errors
resp, err := client.ZoneDetails(ctx, zoneID)
if err != nil {
var apiErr *cfapi.apiError
if errors.As(err, &apiErr) {
log.Error().Str("code", apiErr.Code.String()).Msg(apiErr.Message)
}
return fmt.Errorf("cloudflare api call failed: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// validate identifiers before the API call
if zoneID == "" {
return errors.New("zone ID must not be empty")
}
if !strings.Contains(accountTag, "-") && len(accountTag) != 32 {
return fmt.Errorf("account tag %q is not a valid identifier", accountTag)
} Type guard
func isCompoundAPIError(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "API errors: ")
} Try / catch
err := resp.checkErrors()
if err != nil {
if isCompoundAPIError(err) {
for _, part := range strings.Split(strings.TrimPrefix(err.Error(), "API errors: "), "; ") {
log.Warn().Msg("cloudflare api error: " + part)
}
}
return fmt.Errorf("cloudflare request rejected: %w", err)
} Prevention
- Validate IDs, names, and payload fields against the Cloudflare API schema before sending
- Check API token scope/permissions when errors mention authentication
- Log the full envelope (Messages + Errors) to see every compound error entry
- Back off and retry only on documented retryable codes (rate limits)
When it happens
Trigger: checkErrors is invoked from parseResponseEnvelope and statusCodeToError whenever the decoded response envelope has len(Errors) > 1 — the Cloudflare API returned HTTP 2xx/4xx/5xx with multiple error entries (e.g. several validation failures for one request).
Common situations: Batching operations (DNS record updates, tunnel config changes) where several fields fail validation at once; an invalid API token triggering multiple authorization error entries; rate/plan limits reported alongside a validation error; malformed zone or account IDs producing compound errors.
Related errors
- ErrAPINoSuccess
- Failed to fetch page. Server returned: %d
- Create Tunnel API call failed
- failed to get checksums: {0}
- failed to upload checksum: {0}
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/0396036f90e15303.
Report an issue: GitHub.