cloudflare/cloudflared · error
Failed to fetch page. Server returned: %d
Error message
Failed to fetch page. Server returned: %d
What it means
fetchPage returns this error when fetching a paginated result page yields an unexpected HTTP status that is neither a successful response nor one of the mapped sentinel codes. The message embeds the raw status code so the developer can see exactly what the server returned. It effectively means the pagination loop hit an unrecognized or failed server response.
Source
Thrown at cfapi/base_client.go:180
}
return fullResponse, nil
}
func fetchPage[T any](requestFn func(int) (*http.Response, error), page int) (*response, []*T, error) {
pageResp, err := requestFn(page)
if err != nil {
return nil, nil, errors.Wrap(err, "REST request failed")
}
defer pageResp.Body.Close()
if pageResp.StatusCode == http.StatusOK {
envelope, err := parseResponseEnvelope(pageResp.Body)
if err != nil {
return nil, nil, err
}
var parsedRspBody []*T
return envelope, parsedRspBody, parseResponseBody(envelope, &parsedRspBody)
}
return nil, nil, errors.New(fmt.Sprintf("Failed to fetch page. Server returned: %d", pageResp.StatusCode))
}
type response struct {
Success bool `json:"success,omitempty"`
Errors []apiError `json:"errors,omitempty"`
Messages []string `json:"messages,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
Pagination Pagination `json:"result_info,omitempty"`
}
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 {View on GitHub (pinned to 2253eeeb25)
Solutions
- Read the embedded status code: 429/5xx warrant a retry with backoff, 4xx indicates request problems
- Add retry-with-backoff around the listing call for 5xx/429 statuses
- Check the Cloudflare status page for API incidents if failures persist
- Log the response body (if available) for statuses not mapped to sentinels
Example fix
// before
tunnels, err := client.ListTunnels(ctx, accountTag)
if err != nil {
return err
}
// after
tunnels, err := client.ListTunnels(ctx, accountTag)
if err != nil {
if retriable(err) { // e.g. status 429 or 5xx in message
time.Sleep(backoff)
tunnels, err = client.ListTunnels(ctx, accountTag)
}
if err != nil {
return err
}
} Defensive patterns
Strategy: retry
Try / catch
err := doList(ctx)
if err != nil {
var status int
if n, _ := fmt.Sscanf(err.Error(), "Failed to fetch page. Server returned: %d", &status); n == 1 && (status == 429 || status >= 500) {
// exponential backoff retry
}
} Prevention
- Add retry with exponential backoff and jitter around paginated list calls
- Respect Retry-After on 429 responses
- Monitor Cloudflare status for API incidents
- Keep page sizes modest for very large accounts
When it happens
Trigger: Calling any paginated listing API (e.g. ListTunnels) where the server responds with a status other than 200 and the codes handled by statusCodeToError (401/400/404 etc.) — e.g. 500, 502, 503, 429 from Cloudflare.
Common situations: Cloudflare API incidents or maintenance windows; rate limiting (429) during bulk listings; proxies/CDNs injecting error pages; very large account listings triggering server errors.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- ErrAPINoSuccess
- API errors: %s
- 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/9756097dd3ab8c97.
Report an issue: GitHub.