cloudflare/cloudflared · error
chmod token file at %s: %w
Error message
chmod token file at %s: %w
What it means
After opening the token file, createTokenFileUnix calls os.Chmod(path, 0600) because OpenFile will not tighten permissions on a pre-existing file. If the chmod fails, the error is wrapped as 'chmod token file at <path>: <cause>'. Leaving the file with loose permissions would expose the tunnel credential, so this is deliberately fatal.
Source
Thrown at cmd/cloudflared/common_service.go:41
return nil
}
return fmt.Errorf("create config dir at %s: %w", configDir, err)
}
return nil
}
func createTokenFileUnix(path string) error {
const tokenPerms os.FileMode = 0o600
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, tokenPerms) //nolint:gosec // All callers of this function construct path from constant strings or well-known env vars (e.g., $HOME)
if err != nil {
return fmt.Errorf("create token file at %s: %w", path, err)
}
defer func() { _ = f.Close() }()
// If the file already existed with unrestrictive permissions, os.OpenFile
// will not update its permissions, so perform an extra os.Chmod
if err := os.Chmod(path, tokenPerms); err != nil {
return fmt.Errorf("chmod token file at %s: %w", path, err)
}
return nil
}
// Write out the token file to the configuration directory with the correct
// permissions. Since the method used to restrict the permissions is platform
// dependent, make the function used to restrict the permissions an injectable
// dependency
func writeTokenToFile(path string, token string) error {
if _, err := tunnel.ParseToken(token); err != nil {
return cliutil.UsageError("Provided tunnel token is not valid (%s).", err)
}
if err := createTokenFile(path); err != nil {
return fmt.Errorf("create token file at %s: %w", path, err)
}
View on GitHub (pinned to 2253eeeb25)
Solutions
- chown the existing token file to the user running cloudflared, or delete it and rerun so it is recreated with 0600
- Remove immutable/append-only attributes: `chattr -i <path>`
- Run as the same (privileged) user that originally created the file
- Avoid sharing the token path across users; give each principal its own cred-file
Example fix
// before sudo cloudflared tunnel token --cred-file /etc/cloudflared/token.json TUNNEL_ID # file now root-owned cloudflared tunnel token --cred-file /etc/cloudflared/token.json TUNNEL_ID # chmod fails // after sudo chown $(id -u):$(id -g) /etc/cloudflared/token.json cloudflared tunnel token --cred-file /etc/cloudflared/token.json TUNNEL_ID
Defensive patterns
Strategy: try-catch
Validate before calling
if info, err := os.Stat(path); err == nil && info.Mode().Perm() != 0o600 {
if err := os.Chmod(path, 0o600); err != nil {
return fmt.Errorf("cannot tighten permissions on %s: %w", path, err)
}
} Try / catch
if err := createTokenFileUnix(path); err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) && errors.Is(pathErr.Err, syscall.EPERM) {
return fmt.Errorf("cannot chmod %s (owned by someone else?); remove it and rerun as the current user", path)
}
return err
} Prevention
- Always create/refresh the token file as the same user that owns it
- Avoid root-created credential files consumed by unprivileged services; chown after install
- Never set immutable flags on credential files
- Verify effective UID matches the file owner before rerunning token commands
When it happens
Trigger: The token file already exists but is owned by another user (created previously by root), so the current user cannot chmod it; the filesystem does not support chmod; ACLs/immutable attributes block the change.
Common situations: First run as root created the token file, later runs as a service user attempt to refresh it; an immutable flag (chattr +i) was set on the credential file; NFS exports squashing ownership.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- The file-writing error is: %v / The delete tunnel error is:
- create config dir at %s: %w
- create token file at %s: %w
- failed to copy %s to %s: %w
- error creating %s: %v
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/7bad1715c4175291.
Report an issue: GitHub.