makeplane/plane · error · DRFValidationError

invalid_value_type

invalid_value_type

Error message

Value for '{key}' must be a scalar, null, or list/tuple of scalars

What it means

Raised by _validate_leaf when a leaf field's value is not a scalar, not None, and not a list/tuple. The backend only allows None, str/int/float/bool, or lists of scalars; passing a bare dict, a set, or any other object as a field value is rejected because it cannot be coerced into the QueryDict string form the filterset expects.

Source

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

                    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. Replace dict/object values with the relevant scalar: {"state":"open"} or {"state_id":3}.
  2. If you need sub-field matching, declare it as a relationship filter on the filterset and use the appropriate lookup suffix.
  3. Convert Python sets to lists before serializing.

Example fix

// before
?filters={"state":{"name":"open"}}
// after
?filters={"state":"open"}
Defensive patterns

Strategy: type-guard

Validate before calling

def assert_leaf_values_scalar(leaf):
    for k, v in leaf.items():
        if isinstance(v, (list, tuple)):
            continue
        if not (v is None or isinstance(v, (str, int, float, bool))):
            raise ValueError(f"value for '{k}' must be scalar or null, got {type(v).__name__}")

Type guard

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

Prevention

When it happens

Trigger: GET .../?filters={"state":{"name":"open"}} (dict as value); GET .../?filters={"priority":{}} ; programmatic input that forwards a Django model instance or set object as a value.

Common situations: Client reuses an object representation where a scalar ID/name is expected; Python callers passing a set instead of a list; nested filter fragment mistaken for a value.

Related errors


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