cloudflare/cloudflared · error
could not find program data directory, %s env var must be se
Error message
could not find program data directory, %s env var must be set
What it means
cloudflared stores its Windows service configuration (including the tunnel token file) under %PROGRAMDATA%\<configDirName>. getConfigDir reads the PROGRAMDATA environment variable and throws this error when it is unset, because it cannot locate the program-data directory. It is called by installWindowsService and uninstallWindowsService during service installation/removal.
Source
Thrown at cmd/cloudflared/windows_service.go:295
}
case err := <-errC:
if err != nil {
elog.Error(1, fmt.Sprintf("cloudflared terminated with error %v", err))
ssec = true
errno = 1
} else {
elog.Info(1, "cloudflared terminated without error")
errno = 0
}
return
}
}
}
func getConfigDir() (string, error) {
progDat, progDatSet := os.LookupEnv(programDataEnvVar)
if !progDatSet {
return "", fmt.Errorf("could not find program data directory, %s env var must be set", programDataEnvVar)
}
return filepath.Join(progDat, configDirName), nil
}
func installWindowsService(c *cli.Context) error {
zeroLogger := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
zeroLogger.Info().Msg("Installing cloudflared Windows service")
exepath, err := os.Executable()
if err != nil {
return errors.Wrap(err, "Cannot find path name that start the process")
}
m, err := mgr.Connect()
if err != nil {
return errors.Wrap(err, "Cannot establish a connection to the service control manager")
}
defer m.Disconnect()View on GitHub (pinned to 2253eeeb25)
Solutions
- Ensure PROGRAMDATA is set system-wide (it is by default: C:\ProgramData) — check `echo %PROGRAMDATA%`
- Run the install/uninstall from a normal elevated cmd/PowerShell session, not a stripped environment
- Set it explicitly for the invocation: set PROGRAMDATA=C:\ProgramData && cloudflared service install <args>
- If launched by another service/scheduler, add PROGRAMDATA to that task's environment
Example fix
# before (stripped shell) cloudflared service install <token> // after (cmd) set PROGRAMDATA=C:\ProgramData cloudflared service install <token>
Defensive patterns
Strategy: validation
Validate before calling
# cmd pre-check
if "%PROGRAMDATA%"=="" (echo PROGRAMDATA is not set & exit /b 1)
# PowerShell pre-check
if (-Not $env:PROGRAMDATA) { throw 'PROGRAMDATA env var must be set before service install' } Try / catch
if err := installWindowsService(ctx); err != nil {
if strings.Contains(err.Error(), "program data directory") {
return fmt.Errorf("PROGRAMDATA env var missing; run from a normal elevated shell: %w", err)
}
return err
} Prevention
- Run service install from a standard elevated cmd/PowerShell, not stripped environments
- Avoid launching cloudflared install from containers or custom runners that clear the env
- Keep the system PROGRAMDATA variable intact (default C:\ProgramData)
- Verify with `echo %PROGRAMDATA%` before installing
When it happens
Trigger: os.LookupEnv("PROGRAMDATA") returns ok=false — the variable is not defined in the process environment when service install/uninstall runs.
Common situations: Launching cloudflared from a stripped environment (custom service runner, scheduled task, or SSH session where the user profile/PROGRAMDATA is not populated); running inside a container or under a tool that clears the environment; a corrupted system environment variable block.
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
- locate config dir: %w
- cloudflared service is already installed at ${service}; if y
- Error during update : %s;
- create token security descriptor: %w
- convert path to UTF-16: %w
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/e0689d02844dda59.
Report an issue: GitHub.