HumanSignal/label-studio · error · ValidationError

User filter " " does not support operator " ". Allowed: .

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.

Solutions

  1. Use one of the operators listed in the error message for that field
  2. Consult allowed_user_filter_operators(field) to build the operator menu dynamically
  3. If a legacy operator was intended, keep it as-is — legacy names are still accepted
  4. 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

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


AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29). Data as JSON: /api/errors/a48d5825d534449f. Report an issue: GitHub.

Appendix: 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_value

View on GitHub (pinned to 0b49e9b539)