cloudflare/cloudflared · error
create token file at %s: %w
Error message
create token file at %s: %w
What it means
createTokenFileUnix opens (or creates) the token file with os.OpenFile(O_RDWR|O_CREATE, 0600). A failure is wrapped as 'create token file at <path>: <cause>'. This means the token file could not be opened or created, typically due to permissions, a read-only filesystem, or the path being a directory.
Source
Thrown at cmd/cloudflared/common_service.go:34
const (
defaultTokenFile = "token"
)
func ensureConfigDirExists(configDir string) error {
if err := os.Mkdir(configDir, 0o755); err != nil { //nolint:gosec // config dir must be traversable by non-root user
if errors.Is(err, os.ErrExist) {
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 {View on GitHub (pinned to 2253eeeb25)
Solutions
- Run the command with sufficient privileges (sudo) or point --cred-file at a user-writable path
- Check that the target path is not an existing directory and remove/rename it
- Verify the filesystem is writable (mount flags, disk space)
- Check SELinux/AppArmor audit logs if permissions look correct
Example fix
// before cloudflared tunnel token --cred-file /etc/cloudflared/token.json TUNNEL_ID // after sudo 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 {
if info.IsDir() {
return fmt.Errorf("token path %s is a directory", path)
}
} else if !os.IsNotExist(err) {
return err
}
if err := unix.Access(filepath.Dir(path), unix.W_OK); err != nil {
return fmt.Errorf("cannot write in %s", filepath.Dir(path))
} Try / catch
if err := createTokenFileUnix(path); err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) && (errors.Is(pathErr.Err, syscall.EACCES) || errors.Is(pathErr.Err, syscall.EPERM)) {
return fmt.Errorf("permission denied creating %s; try sudo or a writable --cred-file", path)
}
return err
} Prevention
- Run the token command with the same user that will read the token later
- Keep token paths under directories you own or manage with sudo
- Check for a directory already occupying the token file path
- Verify mount flags (rw) and free space before writing credentials
When it happens
Trigger: The parent directory is not writable by the current user; the path exists as a directory; the filesystem is read-only; SELinux/AppArmor denies the open.
Common situations: Writing the token into /etc/cloudflared without sudo; containers with read-only rootfs; a directory was accidentally created at the token file path; disk-full edge cases on create.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- The file-writing error is: %v / The delete tunnel error is:
- create config dir at %s: %w
- chmod 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/7b2b55db21da7c06.
Report an issue: GitHub.