HumanSignal/label-studio · error · ValidationError
User filter "{field_name}" does not support operator "{opera
Error message
User filter "{field_name}" does not support operator "{operator}". Allowed: {allowed_label}. What it means
validate_user_filter_operator checks a scalar-valued user filter's operator against the per-field allowlist returned by allowed_user_filter_operators(field_name); legacy operators in LEGACY_USER_FILTER_OPERATORS are still tolerated. If the operator is not allowed for that field, ValidationError is raised naming the field, the operator, and the allowed set.
Source
Thrown at label_studio/data_manager/managers.py:116
can recover historical views.
"""
if field_name not in USER_FILTER_FIELDS:
return
if isinstance(value, list):
if operator not in USER_FILTER_VALUE_OPERATORS:
allowed = ', '.join(sorted(USER_FILTER_VALUE_OPERATORS))
raise ValidationError(f'List-valued user filters support only these operators: {allowed}.')
return
allowed = allowed_user_filter_operators(field_name)
if operator in allowed:
return
if operator in LEGACY_USER_FILTER_OPERATORS:
return
allowed_label = ', '.join(sorted(allowed))
raise ValidationError(
f'User filter "{field_name}" does not support operator "{operator}". Allowed: {allowed_label}.'
)
def normalize_persisted_user_filter(field_name, operator, value):
"""Recover historical user-filter shapes without relaxing validation for new writes."""
if field_name not in USER_FILTER_FIELDS:
return operator, value
if operator == Operator.EMPTY:
if field_name not in USER_FILTER_EMPTY_FIELDS:
# Drop unsupported empty (e.g. skipped_by_annotator) to a no-op contains.
return Operator.CONTAINS, []
try:
empty_value = cast_bool_from_str(value)
except ValueError:
return Operator.CONTAINS, []
if isinstance(empty_value, bool):
return operator, empty_valueView on GitHub (pinned to 0b49e9b539)
Solutions
- Use one of the operators listed in the error message for that field
- Consult allowed_user_filter_operators(field) to build the operator menu dynamically
- If a legacy operator was intended, keep it as-is — legacy names are still accepted
- Update stale saved views/filters that embed now-disallowed operators
Example fix
// before
{"filter": "filter:tasks:created_by", "operator": "in_list", "value": 3}
// after
{"filter": "filter:tasks:created_by", "operator": "equal", "value": 3} Defensive patterns
Strategy: validation
Validate before calling
from data_manager.managers import allowed_user_filter_operators, LEGACY_USER_FILTER_OPERATORS
allowed = sorted(allowed_user_filter_operators(field)) + sorted(LEGACY_USER_FILTER_OPERATORS)
assert f['operator'] in allowed, f"{f['operator']} not allowed for {field}" Type guard
def operator_allowed(field, op): return op in allowed_user_filter_operators(field) or op in LEGACY_USER_FILTER_OPERATORS
Try / catch
try:
apply_filters(...)
except ValidationError as e:
if 'does not support operator' in str(e): rebuild_filter_with_allowed_operator(e)
else: raise Prevention
- Build filter UI operator dropdowns from allowed_user_filter_operators
- Validate saved views on load and drop unsupported operators
- Add regression tests per field/operator combination
- Keep client and backend operator enums in sync via a shared contract
When it happens
Trigger: Sending a filter like {filter: 'filter:tasks:created_by', operator: 'in_list', value: 3} or any operator not in that field's allowlist through apply_filters/validate().
Common situations: Client UI offering operators the backend doesn't support for a field; copied filter payloads reused across different field types; version drift after operator allowlists were tightened.
Related errors
- List-valued user filters support only these operators: {allo
- `is any of` / `is none of` support Task ID, Inner ID, annota
- Cannot filter on column "{_filter.filter.removeprefix('filte
- Not supported filter type
- Incorrect value type in key "{key}" = "{value}". It should b
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/a48d5825d534449f.
Report an issue: GitHub.