makeplane/plane · error · DRFValidationError
invalid_operator_children
invalid_operator_children
Error message
'{op}' must be a non-empty list of filter objects What it means
Raised by _validate_structure when an 'or' or 'and' operator's value is not a list, or is an empty list. The grammar requires or/and to take a non-empty JSON array of objects so the backend always has at least one child to evaluate.
Source
Thrown at apps/api/plane/utils/filters/filter_backend.py:376
)
if len(logical_keys) == 1:
op_key = logical_keys[0]
# must not mix operator with other keys
if len(node) != 1:
raise DRFValidationError(
{
"message": (f"Cannot mix logical operator '{op_key}' with field keys at the same level"),
"code": "mixed_operator_and_fields",
}
)
op = op_key.lower()
value = node[op_key]
if op in ("or", "and"):
if not isinstance(value, list) or len(value) == 0:
raise DRFValidationError(
{
"message": f"'{op}' must be a non-empty list of filter objects",
"code": "invalid_operator_children",
}
)
for child in value:
if not isinstance(child, dict):
raise DRFValidationError(
{
"message": f"All children of '{op}' must be JSON objects",
"code": "invalid_operator_child_type",
}
)
self._validate_structure(
child,
max_depth=max_depth,
current_depth=current_depth + 1,
)View on GitHub (pinned to 1c8a60f858)
Solutions
- Use a non-empty array of objects: {"or":[{"state":"open"},{"state":"closed"}]}.
- If you have only one clause, you do not need an operator wrapper at all — send the leaf directly.
- Filter out empty operator groups before serializing.
Example fix
// before
?filters={"or":{}}
// after
?filters={"or":[{"state":"open"}]} Defensive patterns
Strategy: type-guard
Validate before calling
def assert_operator_children(node):
for k, v in node.items():
if isinstance(k, str) and k.lower() in ('or', 'and'):
if not isinstance(v, list) or len(v) == 0:
raise ValueError(f"'{k}' must be a non-empty list") Type guard
function isNonEmptyListOfObjects(v) {
return Array.isArray(v) && v.length > 0 && v.every(x => typeof x === 'object' && x !== null && !Array.isArray(x));
} Prevention
- Skip the or/and wrapper when there is only one clause — send the leaf directly.
- Strip empty operator groups during client serialization.
When it happens
Trigger: GET .../?filters={"or":{}} (object instead of array); GET .../?filters={"and":[]} (empty array); GET .../?filters={"or":"state"} (string value); GET .../?filters={"and":null}.
Common situations: Treating 'and'/'or' as objects keyed by field name; serialization that emits [] when a clause list is empty; client sets the value to None when no clauses are added.
Related errors
- invalid_filter_node
- empty_filter_object
- multiple_logical_operators
- mixed_operator_and_fields
- invalid_operator_child_type
AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12).
Data as JSON: /api/errors/e91db387ce5a2f93.
Report an issue: GitHub.