{"record":{"id":"b2563e4dd1abd322","repo":"HumanSignal/label-studio","slug":"filter-value-must-be-a-list-for-is-any-of-is","errorCode":null,"errorMessage":"Filter value must be a list for `is any of` / `is none of`.","messagePattern":"Filter value must be a list for `is any of` / `is none of`\\.","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"label_studio/data_manager/managers.py","lineNumber":587,"sourceCode":"    Returns one of:\n      - 'ok'   — proceed with the existing Q(__in=value) branch.\n      - 'none' — empty `in_list` after normalization: append a contradiction so the\n                 row contributes no matches (works correctly for both AND and OR).\n      - 'skip' — empty `not_in_list` after normalization: drop the filter entirely.\n\n    Raises ValidationError for unsupported fields. Only triggers when the *original*\n    operator is in_list / not_in_list, so legacy ``annotations_ids`` contains/not_contains\n    filters handled by ``annotation_id_filter_q`` remain unaffected.\n    \"\"\"\n    if _filter.operator not in (Operator.IN_LIST, Operator.NOT_IN_LIST):\n        return 'ok'\n    if not _is_supported_in_list_field(field_name):\n        raise ValidationError(\n            '`is any of` / `is none of` support Task ID, Inner ID, annotation/prediction counters, '\n            'and task.data.* fields.'\n        )\n    if not isinstance(_filter.value, list):\n        raise ValidationError('Filter value must be a list for `is any of` / `is none of`.')\n    _normalize_in_list_value(_filter)\n    if not _filter.value:\n        return 'none' if _filter.operator == Operator.IN_LIST else 'skip'\n    return 'ok'\n\n\ndef add_result_filter(field_name, _filter, filter_expressions, project):\n    from django.db.models.expressions import RawSQL\n    from tasks.models import Annotation, Prediction\n\n    _class = Annotation if field_name == 'annotations_results' else Prediction\n\n    # Annotation\n    if field_name == 'annotations_results':\n        subquery = Q(\n            id__in=Annotation.objects.annotate(json_str=RawSQL('cast(result as text)', ''))\n            .filter(Q(project=project) & Q(json_str__contains=_filter.value))\n            .filter(task=OuterRef('pk'))","sourceCodeStart":569,"sourceCodeEnd":605,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/data_manager/managers.py#L569-L605","documentation":"When the operator is in_list/not_in_list, validate_in_list_filter requires _filter.value to be a Python list. Any other type raises ValidationError('Filter value must be a list for `is any of` / `is none of`.').","triggerScenarios":"Sending {operator:'in_list', value:'abc'} or value: 5 (scalar/string) instead of an array; a JSON string that was not parsed before validation; a client sending a comma-separated string.","commonSituations":"Hand-written API calls omitting the brackets; double-encoded JSON (value serialized twice); frontend passing the raw input text of a multi-select.","solutions":["Send value as a JSON array: value: [1,2,3]","Parse string inputs with json.loads before submitting","Client-side check Array.isArray(value) when using in_list/not_in_list","Normalize comma-separated input into an array in the UI layer"],"exampleFix":"// before\n{\"operator\": \"in_list\", \"value\": \"1,2,3\"}\n// after\n{\"operator\": \"in_list\", \"value\": [1,2,3]}","handlingStrategy":"type-guard","validationCode":"if f['operator'] in ('in_list', 'not_in_list') and not Array.isArray(f.value):\n  f.value = typeof f.value === 'string' ? f.value.split(',').map(s => s.trim()) : [f.value];","typeGuard":"const isListValue = (v) => Array.isArray(v);","tryCatchPattern":"try {\n  await applyFilters(payload);\n} catch (e) {\n  if (/must be a list/.test(e.message)) { payload.filters = wrapValuesInArrays(payload.filters); return applyFilters(payload); }\n  throw e;\n}","preventionTips":["Coerce scalar inputs to single-element arrays at the form layer","Parse JSON strings before submitting filter payloads","Type filter values as unknown[] for list operators in client code","Add request-level schema validation (zod: z.array(z.unknown()))"],"tags":["validation","filters","type-error","data-manager"],"backgroundTag":"filter-value-type-mismatch","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}