cloudflare/cloudflared · error
failed to run transfer service
Error message
failed to run transfer service
What it means
getTokensFromEdge wraps this error when RunTransfer — the local transfer-service flow that mints a token by relaying through a browser/localhost transfer — returns an error. This is the fallback path used when no cached app or org token can be found or exchanged, so it commonly surfaces as an interactive login failure.
Source
Thrown at token/token.go:398
return "", errors.Wrap(err, "failed to write app token to disk")
}
return appToken, nil
}
}
return getTokensFromEdge(appURL, appInfo.AppAUD, appTokenPath, orgTokenPath, useHostOnly, autoClose, isFedramp, log)
}
// getTokensFromEdge will attempt to use the transfer service to retrieve an app and org token, save them to disk,
// and return the app token.
func getTokensFromEdge(appURL *url.URL, appAUD, appTokenPath, orgTokenPath string, useHostOnly bool, autoClose bool, isFedramp bool, log *zerolog.Logger) (string, error) {
// If no org token exists or if it couldn't be exchanged for an app token, then run the transfer service flow.
// this weird parameter is the resource name (token) and the key/value
// we want to send to the transfer service. the key is token and the value
// is blank (basically just the id generated in the transfer service)
resourceData, err := RunTransfer(appURL, appAUD, keyName, keyName, "", true, useHostOnly, autoClose, isFedramp, log, appTokenPath+".url")
if err != nil {
return "", errors.Wrap(err, "failed to run transfer service")
}
var resp transferServiceResponse
if err = json.Unmarshal(resourceData, &resp); err != nil {
return "", errors.Wrap(err, "failed to marshal transfer service response")
}
// If we were able to get the auth domain and generate an org token path, lets write it to disk.
if orgTokenPath != "" {
if err := os.WriteFile(orgTokenPath, []byte(resp.OrgToken), 0600); err != nil {
return "", errors.Wrap(err, "failed to write org token to disk")
}
}
if err := os.WriteFile(appTokenPath, []byte(resp.AppToken), 0600); err != nil {
return "", errors.Wrap(err, "failed to write app token to disk")
}
return resp.AppToken, nilView on GitHub (pinned to 2253eeeb25)
Solutions
- Run `cloudflared access login <url>` interactively once on a machine with a browser to seed the org token, then copy it to the headless host
- Check that the localhost port the transfer service uses is free and not blocked by firewall/proxy
- Inspect the wrapped RunTransfer error for the concrete failure (port bind, edge HTTP error, browser launch)
- Verify the service can reach the Cloudflare edge (no egress restrictions on the access domain)
Example fix
// headless: reuse an org token minted on an interactive machine scp interactive:~/.cloudflared/org-token-* headless:~/.cloudflared/ # then re-run cloudflared access; it will exchange the org token instead of running the transfer service
Defensive patterns
Strategy: fallback
Validate before calling
// headless preflight: can we reach the edge and is an org token present?
toks, _ := filepath.Glob(homeDir + "/.cloudflared/org-token-*")
if len(toks) == 0 && !isInteractive() {
return fmt.Errorf("no org token cached and no browser available — run 'cloudflared access login' on an interactive host")
} Try / catch
token, err := FetchToken(...)
if err != nil && strings.Contains(err.Error(), "failed to run transfer service") {
// interactive flow unavailable: guide user to manual login
return fmt.Errorf("%w — run 'cloudflared access login <url>' once to authenticate", err)
} Prevention
- Seed org tokens on headless hosts via interactive login + file copy
- Reserve the localhost transfer port; check for conflicts
- Test the browser flow after proxy/firewall changes
- Keep cloudflared updated to avoid transfer-service protocol drift
When it happens
Trigger: getToken finds no usable cached tokens and calls getTokensFromEdge -> RunTransfer, which fails because the local transfer service cannot start (port binding failure), the browser login flow fails, or the edge returns an error during the transfer.
Common situations: Headless environments (CI, SSH-only servers) where the interactive browser flow cannot complete; localhost port conflicts blocking the transfer service; corporate proxies blocking the loopback or edge callbacks; stale/expired org token that cannot be refreshed non-interactively.
Related errors
- Failed to fetch resource
- Failed to read auth methods: %v
- failed to create tunnel
- failed to verify token
- quick tunnel provisioning failed
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/e72d0e40c4c7875a.
Report an issue: GitHub.