{"record":{"id":"463321ca2bbb381e","repo":"cloudflare/cloudflared","slug":"locate-config-dir-w","errorCode":null,"errorMessage":"locate config dir: %w","messagePattern":"locate config dir: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cloudflared/windows_service.go","lineNumber":334,"sourceCode":"\tif err == nil {\n\t\ts.Close()\n\t\treturn errors.New(serviceAlreadyExistsWarn(windowsServiceName))\n\t}\n\tvar extraArgs []string\n\tif c.NArg() > 0 {\n\t\t// The service has been installed using a token e.g.,\n\t\t// $ cloudflared service install <token>\n\t\t//\n\t\t// Write the token file to a config directory so we can start the\n\t\t// service with --token-file.\n\n\t\t// Don't use :=, if we did so we would create a new err variable and\n\t\t// shadow the outer one, causing the defer below to not have access to\n\t\t// the outer err\n\t\tvar configDir string\n\t\tconfigDir, err = getConfigDir()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"locate config dir: %w\", err)\n\t\t}\n\n\t\t// Remove token file if service install fails any point onwards from here\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\tremoveTokenFile(configDir, zeroLogger)\n\t\t\t}\n\t\t}()\n\n\t\tif err = writeTokenToConfigDir(c, configDir); err != nil {\n\t\t\treturn fmt.Errorf(\"write token to configuration directory at %s: %w\", configDir, err)\n\t\t}\n\n\t\textraArgs = buildArgsForTokenFile(configDir)\n\t}\n\n\tconfig := mgr.Config{StartType: mgr.StartAutomatic, DisplayName: windowsServiceDescription}\n\ts, err = m.CreateService(windowsServiceName, exepath, config, extraArgs...)","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cmd/cloudflared/windows_service.go#L316-L352","documentation":"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.","triggerScenarios":"Any call to `cloudflared service install` in an environment where PROGRAMDATA is unset, causing getConfigDir to fail and be wrapped here.","commonSituations":"Same as error 188: stripped environments from custom service runners, scheduled tasks, containers, or corrupted environment variables when installing the cloudflared Windows service.","solutions":["Set/restore the system PROGRAMDATA environment variable (default C:\\ProgramData)","Run the install from a standard elevated cmd/PowerShell window","Prefix the command with the variable: set PROGRAMDATA=C:\\ProgramData && cloudflared service install <args>","Check the wrapped inner message to confirm the root cause is the missing PROGRAMDATA var"],"exampleFix":"# before\n$env:PROGRAMDATA = $null; cloudflared service install <token>\n# after (PowerShell)\n$env:PROGRAMDATA = \"C:\\ProgramData\"\ncloudflared service install <token>","handlingStrategy":"validation","validationCode":"# PowerShell: verify env before invoking install\nif (-Not $env:PROGRAMDATA) { $env:PROGRAMDATA = 'C:\\ProgramData' }\nif (-Not (Test-Path $env:PROGRAMDATA)) { throw \"PROGRAMDATA path $env:PROGRAMDATA does not exist\" }","typeGuard":null,"tryCatchPattern":"if err := installWindowsService(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"locate config dir\") {\n\t\tos.Setenv(\"PROGRAMDATA\", `C:\\ProgramData`) // or re-exec from a normal shell\n\t\treturn installWindowsService(ctx)\n\t}\n\treturn err\n}","preventionTips":["Set PROGRAMDATA explicitly when automating installs","Use the standard elevated installer flow rather than bespoke runners","Confirm the variable with `echo %PROGRAMDATA%` before invoking cloudflared service install","Keep system environment variables uncorrupted (check via System Properties > Environment Variables)"],"tags":["windows","environment","windows-service"],"backgroundTag":"missing-env-var","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}