{"record":{"id":"463f537a5c90b9d8","repo":"cloudflare/cloudflared","slug":"create-config-dir-at-s-w","errorCode":null,"errorMessage":"create config dir at %s: %w","messagePattern":"create config dir at (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cloudflared/common_service.go","lineNumber":25,"sourceCode":"\t\"path/filepath\"\n\n\t\"github.com/rs/zerolog\"\n\t\"github.com/urfave/cli/v2\"\n\n\t\"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil\"\n\t\"github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel\"\n)\n\nconst (\n\tdefaultTokenFile = \"token\"\n)\n\nfunc ensureConfigDirExists(configDir string) error {\n\tif err := os.Mkdir(configDir, 0o755); err != nil { //nolint:gosec // config dir must be traversable by non-root user\n\t\tif errors.Is(err, os.ErrExist) {\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"create config dir at %s: %w\", configDir, err)\n\t}\n\treturn nil\n}\n\nfunc createTokenFileUnix(path string) error {\n\tconst tokenPerms os.FileMode = 0o600\n\tf, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, tokenPerms) //nolint:gosec // All callers of this function construct path from constant strings or well-known env vars (e.g., $HOME)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create token file at %s: %w\", path, err)\n\t}\n\tdefer func() { _ = f.Close() }()\n\n\t// If the file already existed with unrestrictive permissions, os.OpenFile\n\t// will not update its permissions, so perform an extra os.Chmod\n\tif err := os.Chmod(path, tokenPerms); err != nil {\n\t\treturn fmt.Errorf(\"chmod token file at %s: %w\", path, err)\n\t}\n","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cmd/cloudflared/common_service.go#L7-L43","documentation":"ensureConfigDirExists creates the token configuration directory with os.Mkdir(0o755) before a tunnel token is written into it. Any mkdir error other than os.ErrExist is wrapped as 'create config dir at <path>: <cause>'. It usually reflects a filesystem permission problem or a bad path component (e.g. an existing regular file where the directory should be).","triggerScenarios":"writeTokenToConfigDir or buildArgsForConfig calls ensureConfigDirExists while the parent of configDir is not writable, configDir exists as a regular file, or an intermediate path component is missing (os.Mkdir does not MkdirAll).","commonSituations":"Running cloudflared as a non-root user with config dir under /etc/cloudflared; a stale file named like the config dir; HOME pointing to a read-only or non-existent path in containers/systemd units.","solutions":["Check ownership/permissions of the config directory path and chown/chmod it appropriately","Ensure the path is a directory: `ls -ld <configDir>`; remove or rename a conflicting file","Run with elevated privileges if the location requires root, or set the originConfig/config dir to a user-writable path","Create parent directories first (mkdir -p) since os.Mkdir only creates one level"],"exampleFix":"// before\nsudo cloudflared tunnel token --cred-file /etc/cloudflared/token.json TUNNEL_ID\n// after\nsudo mkdir -p /etc/cloudflared && sudo chown $(id -u):$(id -g) /etc/cloudflared\ncloudflared tunnel token --cred-file /etc/cloudflared/token.json TUNNEL_ID","handlingStrategy":"validation","validationCode":"info, err := os.Stat(configDir)\nif err == nil && !info.IsDir() {\n    return fmt.Errorf(\"%s exists and is not a directory\", configDir)\n}\nif os.IsNotExist(err) {\n    if err := os.MkdirAll(filepath.Dir(configDir), 0o755); err != nil {\n        return err\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := ensureConfigDirExists(dir); err != nil {\n    var pathErr *os.PathError\n    if errors.As(err, &pathErr) && errors.Is(pathErr.Err, syscall.EACCES) {\n        return fmt.Errorf(\"no permission to create %s; run as root or choose another config dir\", dir)\n    }\n    return err\n}","preventionTips":["Pre-create the config directory with correct ownership during provisioning","Never shadow the config dir path with a regular file","Remember os.Mkdir creates one level only; create parents with mkdir -p","In containers, mount the config directory as a writable volume"],"tags":["filesystem","directory","permissions"],"backgroundTag":"mkdir-permission-denied","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"}