cloudflare/cloudflared · error

Failed to fetch resource

Error message

Failed to fetch resource

What it means

transferRequest in token/transfer.go polls the Cloudflare Access CLI token-transfer endpoint up to 10 times ('long polling'), returning the payload as soon as a non-empty body arrives. If all 10 poll attempts complete with an empty body, it gives up with this sentinel error. It means the resource (the Access token) was never delivered to the transfer endpoint, i.e. the user never completed the browser login/authorization flow in time.

Source

Thrown at token/transfer.go:130

	baseURL.RawQuery = q.Encode() // and this actual baseURL.
	baseURL.Path = "cdn-cgi/access/cli"
	return baseURL.String(), nil
}

// transferRequest downloads the requested resource from the request URL
func transferRequest(requestURL string, log *zerolog.Logger) ([]byte, string, error) {
	client := &http.Client{Timeout: clientTimeout}
	const pollAttempts = 10
	// we do "long polling" on the endpoint to get the resource.
	for i := 0; i < pollAttempts; i++ {
		buf, key, err := poll(client, requestURL, log)
		if err != nil {
			return nil, "", err
		} else if len(buf) > 0 {
			return buf, key, nil
		}
	}
	return nil, "", errors.New("Failed to fetch resource")
}

// poll the endpoint for the request resource, waiting for the user interaction
func poll(client *http.Client, requestURL string, log *zerolog.Logger) ([]byte, string, error) {
	req, err := http.NewRequest(http.MethodGet, requestURL, nil)
	if err != nil {
		return nil, "", err
	}
	req.Header.Set(userAgentHeader, userAgent)
	resp, err := client.Do(req) // nolint: gosec
	if err != nil {
		return nil, "", err
	}
	defer func() { _ = resp.Body.Close() }()

	// ignore everything other than server errors as the resource
	// may not exist until the user does the interaction
	if resp.StatusCode >= 500 {

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Re-run the command and complete the browser authentication flow promptly (click through SSO before polling finishes).
  2. Check that the browser successfully redirects back to the cdn-cgi/access/cli endpoint (watch for redirect errors or blocked popups).
  3. Verify network/proxy settings allow the machine to reach the Cloudflare Access transfer endpoint from both browser and CLI.
  4. Retry the login; if it recurs, increase the polling attempts/clientTimeout in token/transfer.go or capture zerolog debug output from poll() to see what the endpoint returns.

Example fix

// before: give up after fixed attempts
return nil, "", errors.New("Failed to fetch resource")
// after: give the user more time and a clearer message
const pollAttempts = 30
...
return nil, "", fmt.Errorf("did not receive token after %d polls; complete the browser login and retry", pollAttempts)
Defensive patterns

Strategy: retry

Validate before calling

if requestURL == "" {
    return fmt.Errorf("no transfer URL provided; run cloudflared access login first")
}

Try / catch

buf, key, err := transferRequest(url, log)
if err != nil {
    if err.Error() == "Failed to fetch resource" {
        return fmt.Errorf("login not completed in time; rerun and finish browser auth: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: RunTransfer -> transferRequest exhausts pollAttempts=10 iterations of poll() where each HTTP GET on the request URL succeeds but returns an empty body. No network error occurred — the transfer service simply had no token to hand out within the polling window.

Common situations: Running `cloudflared access login` (or a flow that uses LoginHelper token transfer) and not completing the browser authentication before the poll loop ends; the user closing or abandoning the browser tab; corporate SSO taking longer than the polling budget; the redirect back to the CLI endpoint failing silently so the token is never stored.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/6f5f522a69caad8a. Report an issue: GitHub.