{"record":{"id":"57285fb08848711f","repo":"crowdsecurity/crowdsec","slug":"feature-flag-s-w","errorCode":null,"errorMessage":"feature flag '%s': %w","messagePattern":"feature flag '(.+?)': %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/fflag/features.go","lineNumber":120,"sourceCode":"func validateFeatureName(featureName string) error {\n\tif featureName == \"\" {\n\t\treturn ErrFeatureNameEmpty\n\t}\n\n\tif featureName != strings.ToLower(featureName) {\n\t\treturn ErrFeatureNameCase\n\t}\n\n\tif !featureNameRexp.MatchString(featureName) {\n\t\treturn ErrFeatureNameInvalid\n\t}\n\n\treturn nil\n}\n\nfunc (fr *FeatureRegister) RegisterFeature(feat *Feature) error {\n\tif err := validateFeatureName(feat.Name); err != nil {\n\t\treturn fmt.Errorf(\"feature flag '%s': %w\", feat.Name, err)\n\t}\n\n\tif fr.features == nil {\n\t\tfr.features = make(map[string]*Feature)\n\t}\n\n\tfr.features[feat.Name] = feat\n\n\treturn nil\n}\n\nfunc (fr *FeatureRegister) GetFeature(featureName string) (*Feature, error) {\n\tfeat, ok := fr.features[featureName]\n\tif !ok {\n\t\treturn feat, ErrFeatureUnknown\n\t}\n\n\treturn feat, nil","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/fflag/features.go#L102-L138","documentation":"FeatureRegister.RegisterFeature validates the feature name before adding it to the registry; if validateFeatureName rejects the name, the error is wrapped as \"feature flag '<name>': <reason>\". It fails registration at startup rather than allowing an invalid flag to be set later.","triggerScenarios":"Calling RegisterFeature with a Feature whose Name is empty, contains characters outside the allowed set, or otherwise violates the naming rules enforced by validateFeatureName.","commonSituations":"Typo in a newly registered feature flag name (spaces, uppercase, trailing dash); a nil/empty Name field after constructing Feature programmatically.","solutions":["Read the wrapped reason (after the colon) and correct the feature name to satisfy validateFeatureName","Check the Feature literal for an empty or misspelled Name field","Match the naming convention used by existing flags in pkg/fflag (typically lowercase, dashes allowed)","Register flags through the same code path as existing ones to inherit validation-tested names"],"exampleFix":"// before\nfr.RegisterFeature(&Feature{Name: \"Disable HTTP Feature\"})\n// after\nfr.RegisterFeature(&Feature{Name: \"disable-http-feature\"})","handlingStrategy":"validation","validationCode":"var nameRe = regexp.MustCompile(`^[a-z0-9]+(-[a-z0-9]+)*$`)\nif !nameRe.MatchString(feat.Name) {\n    return fmt.Errorf(\"invalid feature name %q\", feat.Name)\n}","typeGuard":null,"tryCatchPattern":"if err := fr.RegisterFeature(feat); err != nil {\n    var reason string\n    if _, werr := fmt.Sscanf(err.Error(), \"feature flag '%[1]s': %s\", &reason); werr != nil {\n        reason = err.Error()\n    }\n    return fmt.Errorf(\"bad feature flag registration: %s\", reason)\n}","preventionTips":["Follow the lowercase-dash naming of existing flags in pkg/fflag","Never leave Feature.Name empty when constructing programmatically","Add a startup test that registers all known flags","Let validateFeatureName failures fail fast at build/test time, not in production"],"tags":["go","feature-flags","validation","naming"],"backgroundTag":"invalid-identifier-format","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"}