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

  1. Check that the configuration directory exists and is writable by the installing user (create it manually and retry).
  2. Re-run the service install from an elevated (Administrator) shell.
  3. 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.
  4. 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

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


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