{"record":{"id":"aeb90eff6f972ef0","repo":"crowdsecurity/crowdsec","slug":"failed-to-open-feature-flags-file-w","errorCode":null,"errorMessage":"failed to open feature flags file: %w","messagePattern":"failed to open feature flags file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/fflag/features.go","lineNumber":244,"sourceCode":"\t\t\treturn err\n\t\t}\n\n\t\tlogger.Debugf(\"Feature flag: %s=true (from config file). %s\", k, feat.Description)\n\t}\n\n\treturn nil\n}\n\nfunc (fr *FeatureRegister) SetFromYamlFile(path string, logger *logrus.Logger) error {\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\tlogger.Tracef(\"Feature flags config file '%s' does not exist\", path)\n\n\t\t\treturn nil\n\t\t}\n\n\t\treturn fmt.Errorf(\"failed to open feature flags file: %w\", err)\n\t}\n\tdefer f.Close()\n\n\tlogger.Debugf(\"Reading feature flags from %s\", path)\n\n\treturn fr.SetFromYaml(f, logger)\n}\n\n// GetEnabledFeatures returns the list of features that have been enabled by the user\nfunc (fr *FeatureRegister) GetEnabledFeatures() []string {\n\tret := make([]string, 0)\n\n\tfor k, feat := range fr.features {\n\t\tif feat.IsEnabled() {\n\t\t\tret = append(ret, k)\n\t\t}\n\t}\n","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/fflag/features.go#L226-L262","documentation":"SetFromYamlFile opens the feature-flags config file at the given path and delegates parsing to SetFromYaml. A missing file is treated as 'no flags' (nil return), but any other open failure — permission denied, path is a directory, I/O error — is wrapped as this error.","triggerScenarios":"Calling SetFromYamlFile(path) where the file exists but cannot be opened: no read permission, path resolves to a directory, device error, or symlink loop.","commonSituations":"Feature-flags file owned by root while crowdsec runs as another user; config path pointing at a directory; overly restrictive umask after manual config editing.","solutions":["Check file permissions: the runtime user needs read access (chmod/chown)","Verify the path points to a regular file, not a directory","Inspect the wrapped OS error (after the colon) for the exact cause","Move/recreate the config file in the standard config directory (/etc/crowdsec/)"],"exampleFix":"// fix typical permission problem\nsudo chown crowdsec:crowdsec /etc/crowdsec/feature_flags.yaml\nsudo chmod 644 /etc/crowdsec/feature_flags.yaml","handlingStrategy":"try-catch","validationCode":"if st, err := os.Stat(path); err != nil || st.IsDir() {\n    return fmt.Errorf(\"feature flags path %q not a readable file\", path)\n}","typeGuard":null,"tryCatchPattern":"if err := fr.SetFromYamlFile(path, logger); err != nil {\n    if strings.HasPrefix(err.Error(), \"failed to open feature flags file\") {\n        // non-fatal: log and continue with default flags\n        logger.Warnf(\"cannot read %s: %v\", path, err)\n        return nil\n    }\n    return err\n}","preventionTips":["Ensure the runtime user can read the config directory and file","Never point the path at a directory","Set 0644 on feature flag files after editing as root","Rely on the built-in nil return for genuinely missing files — only other open errors surface here"],"tags":["go","filesystem","permissions","config"],"backgroundTag":"file-open-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"}