{"record":{"id":"881e14cbff2b1a28","repo":"crowdsecurity/crowdsec","slug":"reading-console-config-file-s-w","errorCode":null,"errorMessage":"reading console config file '%s': %w","messagePattern":"reading console config file '(.+?)': %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csconfig/console.go","lineNumber":80,"sourceCode":"\treturn ret\n}\n\nfunc (c *LocalApiServerCfg) LoadConsoleConfig() error {\n\tc.ConsoleConfig = &ConsoleConfig{}\n\tif _, err := os.Stat(c.ConsoleConfigPath); err != nil && os.IsNotExist(err) {\n\t\tlog.Debugf(\"no console configuration to load\")\n\n\t\tc.ConsoleConfig.ShareCustomScenarios = new(true)\n\t\tc.ConsoleConfig.ShareTaintedScenarios = new(true)\n\t\tc.ConsoleConfig.ShareManualDecisions = new(false)\n\t\tc.ConsoleConfig.ShareContext = new(false)\n\n\t\treturn nil\n\t}\n\n\tyamlFile, err := os.ReadFile(c.ConsoleConfigPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"reading console config file '%s': %w\", c.ConsoleConfigPath, err)\n\t}\n\n\terr = yaml.Unmarshal(yamlFile, c.ConsoleConfig)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"parsing console config file '%s': %w\", c.ConsoleConfigPath, err)\n\t}\n\n\tif c.ConsoleConfig.ShareCustomScenarios == nil {\n\t\tlog.Debugf(\"no share_custom scenarios found, setting to true\")\n\t\tc.ConsoleConfig.ShareCustomScenarios = new(true)\n\t}\n\n\tif c.ConsoleConfig.ShareTaintedScenarios == nil {\n\t\tlog.Debugf(\"no share_tainted scenarios found, setting to true\")\n\t\tc.ConsoleConfig.ShareTaintedScenarios = new(true)\n\t}\n\n\tif c.ConsoleConfig.ShareManualDecisions == nil {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csconfig/console.go#L62-L98","documentation":"LoadConsoleConfig reads the console config file after confirming it exists; the existence check tolerates a missing file, but any other os.ReadFile failure — permission denied, path is a directory, I/O error — is wrapped with this prefix.","triggerScenarios":"crowdsec startup where config/console.yaml (or api.server.console_config_path) exists per os.Stat but cannot be read: permission denied, it's a directory, or a filesystem error.","commonSituations":"File owned by root with 0600 while the service runs as crowdsec; console_config_path accidentally pointing to a directory; NFS/disk errors; SELinux denial blocking read.","solutions":["Fix file permissions so the crowdsec user can read it (`chmod/chown`)","Check it's a regular file, not a directory (`file /etc/crowdsec/console.yaml`)","Check audit logs for SELinux/AppArmor denials","Delete the file if unneeded — absence falls back to defaults"],"exampleFix":"// before\n-rw------- root root /etc/crowdsec/console.yaml\n// after\nsudo chown crowdsec:crowdsec /etc/crowdsec/console.yaml\nsudo chmod 640 /etc/crowdsec/console.yaml","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(consolePath); err == nil && fi.IsDir() { log.Fatalf(\"console_config_path is a directory: %s\", consolePath) }","typeGuard":null,"tryCatchPattern":"if err := serverCfg.LoadConsoleConfig(); err != nil {\n\tvar pe *os.PathError\n\tif errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {\n\t\tlog.Warnf(\"console.yaml unreadable, using defaults: %v\", pe)\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Deploy console.yaml with ownership crowdsec:crowdsec mode 640","Don't place console.yaml under root-only directories","Re-check perms after package upgrades or config management runs"],"tags":["file","permissions","console","config"],"backgroundTag":"file-read-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}