makeplane/plane · error · DRFValidationError

non_scalar_list_item

non_scalar_list_item

Error message

List value for '{key}' must contain only scalar items

What it means

Raised by _validate_leaf when a list/tuple value contains an item that is not a scalar. _is_scalar accepts None, str, int, float, bool; nested lists, dicts, or other objects inside a list value would not survive serialization into the QueryDict that feeds the filterset.

Source

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

                raise DRFValidationError(
                    {
                        "message": "Logical operators cannot appear in a leaf filter object",
                        "code": "operator_in_leaf",
                    }
                )

            # Lists/Tuples must contain only scalar values
            if isinstance(value, (list, tuple)):
                if len(value) == 0:
                    raise DRFValidationError(
                        {
                            "message": f"List value for '{key}' must not be empty",
                            "code": "empty_list_value",
                        }
                    )
                for item in value:
                    if not self._is_scalar(item):
                        raise DRFValidationError(
                            {
                                "message": f"List value for '{key}' must contain only scalar items",
                                "code": "non_scalar_list_item",
                            }
                        )
                continue

            # Scalars and None are allowed
            if not self._is_scalar(value):
                raise DRFValidationError(
                    {
                        "message": (f"Value for '{key}' must be a scalar, null, or list/tuple of scalars"),
                        "code": "invalid_value_type",
                    }
                )

    def _is_scalar(self, value):
        return value is None or isinstance(value, (str, int, float, bool))

View on GitHub (pinned to 1c8a60f858)

Solutions

  1. Flatten list values to scalars: {"state__in":["open","closed"]}.
  2. If the source is a list of objects, map to the scalar field first: objs.map(o => o.id).
  3. Validate each item with typeof checks before serializing.

Example fix

// before
?filters={"id__in":[{"id":1},{"id":2}]}
// after
?filters={"id__in":[1,2]}
Defensive patterns

Strategy: type-guard

Validate before calling

def assert_list_items_scalar(leaf):
    for k, v in leaf.items():
        if isinstance(v, (list, tuple)):
            for item in v:
                if not (item is None or isinstance(item, (str, int, float, bool))):
                    raise ValueError(f"list value for '{k}' contains non-scalar item: {item!r}")

Type guard

function isScalar(v) {
  return v === null || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';
}
function listValuesAreScalar(leaf) {
  return Object.entries(leaf).every(([k, v]) => !Array.isArray(v) || v.every(isScalar));
}

Prevention

When it happens

Trigger: GET .../?filters={"state__in":[{"name":"open"}]} (list of objects); GET .../?filters={"tags__in":[['urgent']]} (nested array); GET .../?filters={"id__in":[123,"abc",[456]]}.

Common situations: Passing a list of ORM objects or dicts from a serializer; client that does not unwrap nested arrays; sending composite values where the filterset expects scalars.

Related errors


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