cloudflare/cloudflared · error
write token to configuration directory at %s: %w
Error message
write token to configuration directory at %s: %w
What it means
Wraps any error that occurred while writing the service token file into the cloudflared configuration directory during Windows service installation (installWindowsService). The wrapper includes the config directory path so the operator can see where the token was expected to be persisted. It is a wrapping error: the underlying cause (permissions, path, HTTP failure fetching the token) is in the %w chain.
Source
Thrown at cmd/cloudflared/windows_service.go:345
// Don't use :=, if we did so we would create a new err variable and
// shadow the outer one, causing the defer below to not have access to
// the outer err
var configDir string
configDir, err = getConfigDir()
if err != nil {
return fmt.Errorf("locate config dir: %w", err)
}
// Remove token file if service install fails any point onwards from here
defer func() {
if err != nil {
removeTokenFile(configDir, zeroLogger)
}
}()
if err = writeTokenToConfigDir(c, configDir); err != nil {
return fmt.Errorf("write token to configuration directory at %s: %w", configDir, err)
}
extraArgs = buildArgsForTokenFile(configDir)
}
config := mgr.Config{StartType: mgr.StartAutomatic, DisplayName: windowsServiceDescription}
s, err = m.CreateService(windowsServiceName, exepath, config, extraArgs...)
if err != nil {
return errors.Wrap(err, "Cannot install service")
}
defer s.Close()
log.Info().Msg("cloudflared agent service is installed")
err = eventlog.InstallAsEventCreate(windowsServiceName, eventlog.Error|eventlog.Warning|eventlog.Info)
if err != nil {
s.Delete()
return errors.Wrap(err, "Cannot install event logger")
}
View on GitHub (pinned to 2253eeeb25)
Solutions
- Check that the configuration directory exists and is writable by the installing user (create it manually and retry).
- Re-run the service install from an elevated (Administrator) shell.
- Inspect the wrapped cause (%w chain) printed with the error to see if it is a permission, path, or token-fetch failure and fix accordingly.
- Alternatively pass the token via flags or a credentials file and avoid token-file persistence.
Example fix
// before: install fails with unwritable dir cloudflared service install eyJ... // after: pre-create config dir and run elevated mkdir %SystemDrive%\Cloudflare 2>nul & icacls %SystemDrive%\Cloudflare /grant Administrators:F cloudflared service install eyJ...
Defensive patterns
Strategy: try-catch
Validate before calling
// Go
dir := configDir
if st, err := os.Stat(dir); err != nil || !st.IsDir() {
if err := os.MkdirAll(dir, 0o700); err != nil { /* fix perms before install */ }
}
if f, err := os.CreateTemp(dir, "tok"); err != nil { /* dir not writable */ } else { f.Close(); os.Remove(f.Name()) } Try / catch
if err := writeTokenToConfigDir(c, configDir); err != nil {
var perr *fs.PathError
if errors.As(err, &perr) { log.Printf("check permissions on %s: %v", configDir, perr) }
return fmt.Errorf("write token to configuration directory at %s: %w", configDir, err)
} Prevention
- Run service install from an elevated shell
- Pre-create and permission the config directory before install
- Check disk space and AV/Group-Policy write restrictions on the config dir
When it happens
Trigger: Running `cloudflared service install <token>` on Windows when writeTokenToConfigDir fails: config directory cannot be created or is unwritable (permission denied, read-only profile), disk full, or the token could not be obtained from the remote API. On failure the deferred hook removes any partial token file.
Common situations: Installing the service under an account lacking write access to %USERPROFILE%\.cloudflared or the system config dir; running the installer from a non-elevated shell; Group Policy restricting writes; network/API errors when fetching the tunnel token.
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
- write token to %s: %w
- failed to copy %s to %s: %w
- error determining executable path: %w
- failed to create lock file %s
- failed to generate app token file path
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/d7a3783be2e51d8a.
Report an issue: GitHub.