{"record":{"id":"f703f90e3f2ccf39","repo":"deepset-ai/haystack","slug":"filter-value-must-be-a-list-when-using-operator","errorCode":null,"errorMessage":"Filter value must be a `list` when using operator 'in' or 'not in', received type '{type(filter_value)}'","messagePattern":"Filter value must be a `list` when using operator 'in' or 'not in', received type '(.+?)'","errorType":"exception","errorClass":"FilterError","httpStatus":null,"severity":"error","filePath":"haystack/utils/filters.py","lineNumber":247,"sourceCode":"def _less_than_equal(value: Any, filter_value: Any, strict_datetime_comparison: bool) -> bool:\n    if value is None or filter_value is None:\n        # We can't compare None values reliably using operators '>', '>=', '<', '<='\n        return False\n\n    value, filter_value, comparable = _prepare_ordering_comparison(\n        value=value, filter_value=filter_value, strict_datetime_comparison=strict_datetime_comparison\n    )\n    if not comparable:\n        return False\n    return value <= filter_value\n\n\ndef _in(value: Any, filter_value: Any, strict_datetime_comparison: bool) -> bool:\n    if not isinstance(filter_value, list):\n        msg = (\n            f\"Filter value must be a `list` when using operator 'in' or 'not in', received type '{type(filter_value)}'\"\n        )\n        raise FilterError(msg)\n    return any(_equal(e, value, strict_datetime_comparison) for e in filter_value)\n\n\ndef _not_in(value: Any, filter_value: Any, strict_datetime_comparison: bool) -> bool:\n    return not _in(value=value, filter_value=filter_value, strict_datetime_comparison=strict_datetime_comparison)\n\n\nCOMPARISON_OPERATORS = {\n    \"==\": _equal,\n    \"!=\": _not_equal,\n    \">\": _greater_than,\n    \">=\": _greater_than_equal,\n    \"<\": _less_than,\n    \"<=\": _less_than_equal,\n    \"in\": _in,\n    \"not in\": _not_in,\n}\n","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/utils/filters.py#L229-L265","documentation":"The 'in' and 'not in' operators require the filter value to be a list; _in raises FilterError for any other type. Since _not_in delegates to _in, both operators enforce this.","triggerScenarios":"Filters like {\"operator\": \"in\", \"field\": \"meta.tag\", \"value\": \"news\"} (a bare string) or a dict/int value.","commonSituations":"Forgetting to wrap a single value in a list when switching from '==' to 'in'; programmatic filter builders that pass scalars through.","solutions":["Wrap the value in a list, e.g. [\"news\"].","Use '==' or '!=' if you actually mean single-value equality.","Validate that 'in'/'not in' filter values are lists before applying filters."],"exampleFix":"// before\nfilters = {\"operator\": \"in\", \"field\": \"meta.tag\", \"value\": \"news\"}\n// after\nfilters = {\"operator\": \"in\", \"field\": \"meta.tag\", \"value\": [\"news\"]}","handlingStrategy":"validation","validationCode":"if f.get(\"operator\") in {\"in\", \"not in\"} and not isinstance(f.get(\"value\"), list):\n    f[\"value\"] = [f[\"value\"]]","typeGuard":"def is_list_value(f: dict) -> bool:\n    return f.get(\"operator\") not in {\"in\", \"not in\"} or isinstance(f.get(\"value\"), list)","tryCatchPattern":"try:\n    ok = document_matches_filter(doc, filters)\nexcept FilterError as e:\n    logger.warning(\"invalid filter: %s\", e)\n    ok = False","preventionTips":["Always wrap values in a list for 'in'/'not in'.","Use '=='/'!=' for single-value checks.","Normalize filter values in a shared helper before applying."],"tags":["python","filters","validation","haystack"],"backgroundTag":"invalid-filter-value-type","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}