{"record":{"id":"a7c65c82a0df169e","repo":"cloudflare/cloudflared","slug":"unable-to-find-config-file","errorCode":null,"errorMessage":"unable to find config file","messagePattern":"unable to find config file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/manager.go","lineNumber":74,"sourceCode":"\tnotifier.ConfigDidUpdate(config)\n\n\tm.watcher.Start(m)\n\treturn nil\n}\n\n// GetConfig reads the yaml file from the disk\nfunc (m *FileManager) GetConfig() (Root, error) {\n\treturn m.ReadConfig(m.configPath, m.log)\n}\n\n// Shutdown stops the watcher\nfunc (m *FileManager) Shutdown() {\n\tm.watcher.Shutdown()\n}\n\nfunc readConfigFromPath(configPath string, log *zerolog.Logger) (Root, error) {\n\tif configPath == \"\" {\n\t\treturn Root{}, errors.New(\"unable to find config file\")\n\t}\n\n\tfile, err := os.Open(configPath)\n\tif err != nil {\n\t\treturn Root{}, err\n\t}\n\tdefer file.Close()\n\n\tvar config Root\n\tif err := yaml.NewDecoder(file).Decode(&config); err != nil {\n\t\tif err == io.EOF {\n\t\t\tlog.Error().Msgf(\"Configuration file %s was empty\", configPath)\n\t\t\treturn Root{}, nil\n\t\t}\n\t\treturn Root{}, errors.Wrap(err, \"error parsing YAML in config file at \"+configPath)\n\t}\n\n\treturn config, nil","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/config/manager.go#L56-L92","documentation":"readConfigFromPath loads and parses the cloudflared Root configuration from a given path. If it is handed an empty string, there is no file to open, so it immediately returns 'unable to find config file'. This guards the fast path before os.Open produces its own error.","triggerScenarios":"A caller (e.g. config manager code watching/loading config files) invokes readConfigFromPath with configPath == \"\", typically because no config path was resolved from flags or defaults.","commonSituations":"--config flag not set and no default config file found so the resolved path is empty; environment or service-manager setups that pass an unset variable as the config path; programmatic use of the config manager.","solutions":["Pass an explicit path via --config /path/to/config.yml or set the TUNNEL_CONFIG environment variable","Verify the variable or flag feeding configPath is not empty before calling the manager","Create the expected default config file (~/.cloudflared/config.yml or /etc/cloudflared/config.yml) if you intend defaults to work"],"exampleFix":"// before\nroot, err := readConfigFromPath(cfgPath, log) // cfgPath == \"\"\n// after\nif cfgPath == \"\" {\n    cfgPath = \"/etc/cloudflared/config.yml\"\n}\nroot, err := readConfigFromPath(cfgPath, log)","handlingStrategy":"validation","validationCode":"if configPath == \"\" {\n    return errors.New(\"no cloudflared config path provided; use --config or create ~/.cloudflared/config.yml\")\n}\nif _, err := os.Stat(configPath); os.IsNotExist(err) {\n    return fmt.Errorf(\"config file %s does not exist\", configPath)\n}","typeGuard":"func hasReadableConfig(path string) bool {\n    if path == \"\" { return false }\n    info, err := os.Stat(path)\n    return err == nil && !info.IsDir()\n}","tryCatchPattern":"root, err := readConfigFromPath(cfgPath, log)\nif err != nil && err.Error() == \"unable to find config file\" {\n    // prompt for --config or fall back to default config location\n}","preventionTips":["Always set --config explicitly in service managers and containers","Fail fast on empty config-path variables before launching cloudflared","Keep a default config file at the expected location if you rely on defaults"],"tags":["config","file","missing-file"],"backgroundTag":"missing-config-file","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}