makeplane/plane · warning · DRFValidationError
empty_list_value
empty_list_value
Error message
List value for '{key}' must not be empty What it means
Raised by _validate_leaf when a leaf field's value is a list or tuple of length zero. List values are allowed for filters like __in and __range, but an empty list would expand to a no-op or SQL `IN ()` which is invalid in most databases, so the backend rejects it before it reaches the ORM.
Source
Thrown at apps/api/plane/utils/filters/filter_backend.py:433
{
"message": "Leaf filter must be a non-empty JSON object",
"code": "invalid_leaf",
}
)
for key, value in leaf.items():
if isinstance(key, str) and key.lower() in ("or", "and", "not"):
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(View on GitHub (pinned to 1c8a60f858)
Solutions
- Drop the field key entirely when its list is empty — no filter is usually the intent.
- On the client, filter out empty-list values before serializing: Object.fromEntries(Object.entries(f).filter(([,v]) => !(Array.isArray(v) && v.length === 0))).
- If an empty IN is genuinely desired, replace it with an always-false condition explicitly rather than relying on empty-list semantics.
Example fix
// before
?filters={"state__in":[]}
// after
?filters={} // omit the key, or send a non-empty list Defensive patterns
Strategy: validation
Validate before calling
def drop_empty_list_values(filter_data):
if isinstance(filter_data, dict):
return {k: (drop_empty_list_values(v) if isinstance(v, dict)
else [drop_empty_list_values(c) for c in v] if isinstance(v, list) else v)
for k, v in filter_data.items()
if not (isinstance(v, (list, tuple)) and len(v) == 0)}
return filter_data Type guard
function noEmptyListValues(node) {
if (typeof node !== 'object' || node === null) return true;
if (Array.isArray(node)) return node.every(noEmptyListValues);
return Object.entries(node).every(([k, v]) => !(Array.isArray(v) && v.length === 0))
&& Object.values(node).every(noEmptyListValues);
} Prevention
- Omit __in/__range keys when their list is empty rather than sending [].
- In the UI picker, removing all selected items should also remove the filter clause.
When it happens
Trigger: GET .../?filters={"state__in":[]} ; GET .../?filters={"sequence_id__range":[]} ; client sends an empty selection from a multi-select picker.
Common situations: UI multi-select that submits even when nothing is chosen; programmatic filter that always emits an `__in` key but leaves it empty; clearing a picker without removing the filter clause.
Related errors
- invalid_filter_node
- empty_filter_object
- multiple_logical_operators
- mixed_operator_and_fields
- invalid_operator_children
AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12).
Data as JSON: /api/errors/5972c837dd696538.
Report an issue: GitHub.