{"record":{"id":"81fd463b776a353b","repo":"crowdsecurity/crowdsec","slug":"filter-is-not-allowed-for-ip-scope","errorCode":null,"errorMessage":"filter is not allowed for IP scope","messagePattern":"filter is not allowed for IP scope","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/leakybucket/scopetype.go","lineNumber":25,"sourceCode":"\t\"github.com/expr-lang/expr/vm\"\n\n\t\"github.com/crowdsecurity/crowdsec/pkg/types\"\n)\n\ntype ScopeType struct {\n\tScope         string `yaml:\"type\"`\n\tFilter        string `yaml:\"expression\"`\n\tRunTimeFilter *vm.Program\n}\n\nfunc (s *ScopeType) CompileFilter() error {\n\tif s.Scope == types.Undefined {\n\t\ts.Scope = types.Ip\n\t}\n\n\tif s.Scope == types.Ip {\n\t\tif s.Filter != \"\" {\n\t\t\treturn errors.New(\"filter is not allowed for IP scope\")\n\t\t}\n\n\t\treturn nil\n\t}\n\n\tif s.Scope == types.Range && s.Filter == \"\" {\n\t\treturn nil\n\t}\n\n\tif s.Filter == \"\" {\n\t\treturn errors.New(\"filter is mandatory for non-IP, non-Range scope\")\n\t}\n\n\trunTimeFilter, err := compile(s.Filter, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error compiling the scope filter: %w\", err)\n\t}\n","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/leakybucket/scopetype.go#L7-L43","documentation":"Scope compile-time validation in leakybucket. When a bucket's scope is 'Ip' (or undefined, which defaults to Ip), the scope-level filter must be empty, because IP scope deduplicates events purely on the source IP extracted by the parser; a filter expression makes no sense there and would silently change bucket semantics.","triggerScenarios":"Calling Scope.CompileFilter() on a scope whose Scope field is types.Ip (or types.Undefined) while s.Filter is a non-empty string — typically from a bucket config that declares scope: type: ip together with an expression field.","commonSituations":"Writing a custom scenario YAML and adding an 'expression' under the scope section, copying a non-IP scope config and switching type to ip without removing the filter, or programmatic bucket construction where the filter is set before the scope type.","solutions":["Remove the scope filter (expression) from the bucket configuration since IP scope derives the key from the parsed source IP.","If filtering is actually needed, change the scope type to a non-IP, non-Range scope (e.g. use a filter on a different scope) so a filter is valid.","Use the event-level 'filter' in the scenario definition instead of the scope-level filter to restrict which events are counted."],"exampleFix":"// before\nscope:\n  type: ip\n  expression: evt.Meta.service == 'ssh'\n// after\nscope:\n  type: ip\n# move the condition to the scenario-level filter if needed:\n# filter: evt.Meta.service == 'ssh'","handlingStrategy":"validation","validationCode":"if scope.Scope == types.Ip && scope.Filter != \"\" {\n    return errors.New(\"remove scope filter when using ip scope\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pair scope type ip with an expression field","Use scenario-level filter for event selection, scope only for key derivation","Lint scenario YAML for scope/filter combinations before deploy"],"tags":["crowdsec","configuration","validation"],"backgroundTag":"invalid-config-value","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"}