cloudflare/cloudflared · error

locate config dir: %w

Error message

locate config dir: %w

What it means

installWindowsService needs the cloudflared config directory under %PROGRAMDATA% before it can create the service and write the token file. It calls getConfigDir and, on failure, re-wraps the underlying error ('could not find program data directory...') with 'locate config dir'. This is a wrapper — the root cause is always the missing PROGRAMDATA environment variable from error 188.

Source

Thrown at cmd/cloudflared/windows_service.go:334

	if err == nil {
		s.Close()
		return errors.New(serviceAlreadyExistsWarn(windowsServiceName))
	}
	var extraArgs []string
	if c.NArg() > 0 {
		// The service has been installed using a token e.g.,
		// $ cloudflared service install <token>
		//
		// Write the token file to a config directory so we can start the
		// service with --token-file.

		// 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...)

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Set/restore the system PROGRAMDATA environment variable (default C:\ProgramData)
  2. Run the install from a standard elevated cmd/PowerShell window
  3. Prefix the command with the variable: set PROGRAMDATA=C:\ProgramData && cloudflared service install <args>
  4. Check the wrapped inner message to confirm the root cause is the missing PROGRAMDATA var

Example fix

# before
$env:PROGRAMDATA = $null; cloudflared service install <token>
# after (PowerShell)
$env:PROGRAMDATA = "C:\ProgramData"
cloudflared service install <token>
Defensive patterns

Strategy: validation

Validate before calling

# PowerShell: verify env before invoking install
if (-Not $env:PROGRAMDATA) { $env:PROGRAMDATA = 'C:\ProgramData' }
if (-Not (Test-Path $env:PROGRAMDATA)) { throw "PROGRAMDATA path $env:PROGRAMDATA does not exist" }

Try / catch

if err := installWindowsService(ctx); err != nil {
	if strings.Contains(err.Error(), "locate config dir") {
		os.Setenv("PROGRAMDATA", `C:\ProgramData`) // or re-exec from a normal shell
		return installWindowsService(ctx)
	}
	return err
}

Prevention

When it happens

Trigger: Any call to `cloudflared service install` in an environment where PROGRAMDATA is unset, causing getConfigDir to fail and be wrapped here.

Common situations: Same as error 188: stripped environments from custom service runners, scheduled tasks, containers, or corrupted environment variables when installing the cloudflared Windows service.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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