{"record":{"id":"ee3ac4b1f5a85490","repo":"crowdsecurity/crowdsec","slug":"invalid-contains-value-w-w-ee3ac4","errorCode":null,"errorMessage":"invalid contains value: %w: %w","messagePattern":"invalid contains value: %w: %w","errorType":"validation","errorClass":"InvalidFilter","httpStatus":null,"severity":"error","filePath":"pkg/database/decisions.go","lineNumber":236,"sourceCode":"\n// ExpireDecisionsWithFilter updates the expiration time to now() for the decisions matching the filter, and returns the updated items\nfunc (c *Client) ExpireDecisionsWithFilter(ctx context.Context, filter map[string][]string) (int, []*ent.Decision, error) {\n\tvar (\n\t\terr error\n\t\trng csnet.Range\n\t)\n\n\tcontains := true\n\t// if contains is true, return bans that *contains* the given value (value is the inner)\n\t// else, return bans that are *contained* by the given value (value is the outer)\n\tdecisions := c.Ent.Decision.Query().Where(decision.UntilGT(time.Now().UTC()))\n\n\tfor param, value := range filter {\n\t\tswitch param {\n\t\tcase \"contains\":\n\t\t\tcontains, err = strconv.ParseBool(value[0])\n\t\t\tif err != nil {\n\t\t\t\treturn 0, nil, fmt.Errorf(\"invalid contains value: %w: %w\", err, InvalidFilter)\n\t\t\t}\n\t\tcase \"scopes\":\n\t\t\tdecisions = decisions.Where(decision.ScopeEQ(value[0]))\n\t\tcase \"uuid\":\n\t\t\tdecisions = decisions.Where(decision.UUIDIn(value...))\n\t\tcase \"origin\":\n\t\t\tdecisions = decisions.Where(decision.OriginEQ(value[0]))\n\t\tcase \"value\":\n\t\t\tdecisions = decisions.Where(decision.ValueEQ(value[0]))\n\t\tcase \"type\":\n\t\t\tdecisions = decisions.Where(decision.TypeEQ(value[0]))\n\t\tcase \"ip\", \"range\":\n\t\t\trng, err = csnet.NewRange(value[0])\n\t\t\tif err != nil {\n\t\t\t\treturn 0, nil, fmt.Errorf(\"unable to convert '%s' to int: %w: %w\", value[0], err, InvalidIPOrRange)\n\t\t\t}\n\t\tcase \"scenario\":\n\t\t\tdecisions = decisions.Where(decision.ScenarioEQ(value[0]))","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/decisions.go#L218-L254","documentation":"ExpireDecisionsWithFilter accepts a filter map; when the 'contains' key is present its value must parse as a Go bool via strconv.ParseBool. If the value is not one of 1/t/T/true/TRUE/True/0/f/F/false/FALSE/False, the bool conversion fails and the error is wrapped together with the InvalidFilter sentinel so callers can classify it as a bad filter.","triggerScenarios":"Calling ExpireDecisionsWithFilter (directly or via HandleDeletedDecisionsV3, DeleteDecisions, or the cscli decisions CLI) with filter[\"contains\"] set to a non-boolean string such as \"yes\", \"on\", \"1 \", or \"true1\".","commonSituations":"CLI users passing --contains=yes instead of --contains=true; JSON/API clients sending human-style booleans; automation scripts quoting the value wrongly so it arrives as \"'true'\".","solutions":["Pass a value accepted by strconv.ParseBool: 1, t, T, true, TRUE, True, 0, f, F, false, FALSE, False","Fix the calling code to serialize booleans properly instead of formatting them as yes/no or on/off","Trim whitespace/quotes from the value before building the filter map","Check errors.Is(err, database.InvalidFilter) in the caller to surface a 400-style message to the user"],"exampleFix":"// before\nc.ExpireDecisionsWithFilter(ctx, map[string][]string{\"contains\": {\"yes\"}})\n// after\nc.ExpireDecisionsWithFilter(ctx, map[string][]string{\"contains\": {\"true\"}})","handlingStrategy":"validation","validationCode":"func validContains(v string) bool {\n    _, err := strconv.ParseBool(v)\n    return err == nil\n}\nif !validContains(filterVal) { return fmt.Errorf(\"contains must be a bool, got %q\", filterVal) }","typeGuard":null,"tryCatchPattern":"if _, _, err := client.ExpireDecisionsWithFilter(ctx, filter); err != nil {\n    if errors.Is(err, database.InvalidFilter) {\n        return fmt.Errorf(\"bad filter: %w\", err)\n    }\n    return err\n}","preventionTips":["Serialize booleans with strconv.FormatBool, never string concatenation","Trim user input before building the filter map","Document accepted values (1/t/true, 0/f/false) for CLI users"],"tags":["go","validation","database","filter"],"backgroundTag":"invalid-argument-value","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}