makeplane/plane · error · DRFValidationError

invalid_filter_field

invalid_filter_field

Error message

Filtering on field '{field}' is not allowed

What it means

Raised by _validate_fields when a field name extracted from the filter tree is not present in the view's filterset_class.base_filters keys. base_filters is the declared allowlist of filters (including lookup variants like sequence_id__gte), so this fires on typos, renamed fields, or attempts to filter on a field the view never exposed.

Source

Thrown at apps/api/plane/utils/filters/filter_backend.py:122

        if not allowed_fields:
            # If no FilterSet is configured, reject filtering to avoid unintended exposure # noqa: E501
            raise DRFValidationError(
                {
                    "message": ("Filtering is not enabled for this endpoint (missing filterset_class)"),
                    "code": "filtering_not_enabled",
                }
            )

        # Extract field names from the filter data
        fields = self._extract_field_names(filter_data)

        # Check if all fields are allowed
        for field in fields:
            # Field keys must match FilterSet filter names (including any lookups)
            # Example: 'sequence_id__gte' should be declared in base_filters
            # Special-case __range: require the '<base>__range' filter itself
            if field not in allowed_fields:
                raise DRFValidationError(
                    {
                        "message": f"Filtering on field '{field}' is not allowed",
                        "code": "invalid_filter_field",
                    }
                )

    def _transform_field_name_for_validation(self, field_name):
        """Hook: Transform a field name before validation.

        Override this in subclasses to handle special field naming conventions.

        Args:
            field_name: The original field name from the filter data

        Returns:
            The transformed field name to validate against the FilterSet
        """
        return field_name

View on GitHub (pinned to 1c8a60f858)

Solutions

  1. Inspect the view's filterset_class.declared_filters and base_filters to confirm the exact allowed key names.
  2. Add the missing filter to the filterset, e.g. `archived_at__isnull = django_filters.BooleanFilter(field_name='archived_at', lookup_expr='isnull')`.
  3. Fix the typo / use the correct lookup suffix; remember lookups must be declared individually (sequence_id__gte is a separate key from sequence_id).

Example fix

# before
class IssueFilterSet(BaseFilterSet):
    sequence_id = NumberFilter(field_name='sequence_id')
# client sends {"sequence_id__gte": 5}

# after
class IssueFilterSet(BaseFilterSet):
    sequence_id = NumberFilter(field_name='sequence_id')
    sequence_id__gte = NumberFilter(field_name='sequence_id', lookup_expr='gte')
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = set(view.filterset_class.base_filters.keys())
missing = [f for f in extracted_field_names(filter_data) if f not in ALLOWED]
if missing:
    raise ValueError(f'Unsupported filter fields: {missing}. Allowed: {sorted(ALLOWED)}')

Type guard

def extract_field_names(node):
    fields = []
    if isinstance(node, dict):
        for k, v in node.items():
            if isinstance(k, str) and k.lower() in ('or', 'and'):
                for c in v:
                    fields.extend(extract_field_names(c))
            elif isinstance(k, str) and k.lower() == 'not':
                fields.extend(extract_field_names(v))
            else:
                fields.append(k)
    return fields

Prevention

When it happens

Trigger: GET /api/workspaces/<slug>/issues/?filters={"stat":"open"} (typo); GET .../?filters={"assigneed__in":[...]} (extra d); GET .../?filters={"archived_at__isnull":true} on a view whose filterset does not declare that lookup.

Common situations: Frontend references a field that was renamed in a backend migration; client expects a filter the EE/CE split does not expose; using a Django ORM lookup suffix (__gte, __in, __range) whose filter is not explicitly declared on the filterset.

Related errors


AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12). Data as JSON: /api/errors/bdce5d404d09cbf1. Report an issue: GitHub.