{"record":{"id":"a67c7a730163c1e2","repo":"crowdsecurity/crowdsec","slug":"filter-is-mandatory-for-non-ip-non-range-scope","errorCode":null,"errorMessage":"filter is mandatory for non-IP, non-Range scope","messagePattern":"filter is mandatory for non-IP, non-Range scope","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/leakybucket/scopetype.go","lineNumber":36,"sourceCode":"func (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\n\ts.RunTimeFilter = runTimeFilter\n\n\treturn nil\n}\n","sourceCodeStart":18,"sourceCodeEnd":48,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/leakybucket/scopetype.go#L18-L48","documentation":"Scope validation requiring an expression. For any scope that is neither 'Ip' nor 'Range' (both of which have implicit key derivation), the scope's Filter is what computes the bucket key from the event; an empty filter would make the bucket key undefined, so CompileFilter rejects it and compiles the filter to expr.","triggerScenarios":"Calling Scope.CompileFilter() where s.Scope is a custom/non-IP/non-Range type (e.g. 'metadata', 'range'-like custom scopes) and s.Filter is the empty string; also occurs when the filter is present but fails compilation, producing the wrapped 'error compiling the scope filter' variant.","commonSituations":"Custom scenario YAML declaring a non-ip scope without an 'expression' field, typo'ing the expression key so it parses as empty, or programmatically building a Scope struct and forgetting to set Filter before CompileFilter.","solutions":["Add a valid expr 'expression' under the scope definition in the scenario YAML.","If the intent was IP-keyed bucketing, set scope type to ip (which needs no filter).","If the intent was range-based bucketing, set scope type to range; it also needs no filter."],"exampleFix":"// before\nscope:\n  type: metadata\n// after\nscope:\n  type: metadata\n  expression: evt.Meta.target_user","handlingStrategy":"validation","validationCode":"if scope.Scope != types.Ip && scope.Scope != types.Range && scope.Filter == \"\" {\n    return errors.New(\"non-ip/non-range scope needs an expression\")\n}","typeGuard":null,"tryCatchPattern":"if err := scope.CompileFilter(); err != nil {\n    return fmt.Errorf(\"invalid scope in scenario %s: %w\", name, err)\n}","preventionTips":["Always provide 'expression' when scope type is not ip or range","Verify expression compiles with a local expr test before shipping scenarios","Watch for YAML key typos ('expr' vs 'expression') that yield an empty filter"],"tags":["crowdsec","configuration","validation","expr"],"backgroundTag":"missing-required-config-field","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"}