cloudflare/cloudflared · error

failed to write org token to disk

Error message

failed to write org token to disk

What it means

This error wraps a failure from os.WriteFile when persisting the Cloudflare Access org token to the token path on disk after successfully fetching tokens from the edge. The library throws it because without the org token cached on disk, subsequent runs cannot reuse the org token to exchange for app tokens, breaking the token refresh flow. The underlying err carries the real OS-level cause (permissions, missing directory, disk full).

Source

Thrown at token/token.go:408

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, nil
}

// GetAppInfo discovers the Access application protecting reqURL by requesting
// a signed metadata JWT from the Cloudflare edge. The JWT signature is verified
// against the account's public keys (fetched from the auth domain's JWKS
// endpoint) to prevent an attacker-controlled server from spoofing app identity.
func GetAppInfo(reqURL *url.URL) (*AppInfo, error) {
	// Fetch the metadata JWT from the edge (no redirects followed).
	rawJWT, err := fetchMetadataJWT(reqURL.String())
	if err != nil {

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Check that the directory containing orgTokenPath exists and is writable by the current user (ls -ld on the parent dir); create it with mkdir -p if missing
  2. Re-run as the same user that owns the token directory, or with correct ownership (chown) / appropriate privileges
  3. Check disk space (df -h) and filesystem mount status (read-only mounts)
  4. If running in a container, mount a writable volume for the token path or set a writable token directory
  5. Inspect the wrapped cause in the error message for the exact OS error (e.g. 'permission denied', 'no such file or directory')

Example fix

// before: writing to a path whose directory may not exist
if err := os.WriteFile(orgTokenPath, []byte(resp.OrgToken), 0600); err != nil {
	return "", errors.Wrap(err, "failed to write org token to disk")
}
// after: ensure parent directory exists and is writable first
if err := os.MkdirAll(filepath.Dir(orgTokenPath), 0700); err != nil {
	return "", errors.Wrap(err, "failed to create token directory")
}
if err := os.WriteFile(orgTokenPath, []byte(resp.OrgToken), 0600); err != nil {
	return "", errors.Wrap(err, "failed to write org token to disk")
}
Defensive patterns

Strategy: try-catch

Validate before calling

if info, err := os.Stat(filepath.Dir(tokenPath)); err != nil || !info.IsDir() {
	os.MkdirAll(filepath.Dir(tokenPath), 0700)
}
if err := unix.Access(filepath.Dir(tokenPath), unix.W_OK); err != nil {
	// directory not writable by current user
}

Try / catch

token, err := getToken(ctx, log)
if err != nil && strings.Contains(err.Error(), "failed to write org token to disk") {
	// fix token dir permissions or fall back to non-persistent auth
}

Prevention

When it happens

Trigger: getTokensFromEdge (via getToken) successfully authenticated and got resp.OrgToken from the edge, orgTokenPath was non-empty, but os.WriteFile(orgTokenPath, ...) failed — typically because the parent directory does not exist or is not writable by the current user.

Common situations: Running cloudflared/cloudflared-access as a different user than the one who first authenticated; token dir under $HOME of another user or read-only filesystem; container running as non-root without a writable TUNNEL_TOKEN dir; full disk; overly restrictive umask/SELinux policy.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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