makeplane/plane · error · DRFValidationError
mixed_operator_and_fields
mixed_operator_and_fields
Error message
Cannot mix logical operator '{op_key}' with field keys at the same level What it means
Raised by _validate_structure when a node has exactly one logical-operator key AND at least one other key. The grammar requires the operator object to contain *only* the operator — fields must live in a child object, never alongside or/and/not at the same level.
Source
Thrown at apps/api/plane/utils/filters/filter_backend.py:364
"code": "empty_filter_object",
}
)
logical_keys = [k for k in node.keys() if isinstance(k, str) and k.lower() in ("or", "and", "not")]
if len(logical_keys) > 1:
raise DRFValidationError(
{
"message": ("A filter object cannot contain multiple logical operators at the same level"),
"code": "multiple_logical_operators",
}
)
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:View on GitHub (pinned to 1c8a60f858)
Solutions
- Move sibling fields into a child of the operator: {"and":[{"or":[...]},{"priority":"high"}]}.
- When building objects programmatically, never dict.update an operator object with field keys.
- Treat operator objects as structural only — they hold either an or/and/not key or field keys, never both.
Example fix
// before
?filters={"or":[{"state":"open"}],"priority":"high"}
// after
?filters={"and":[{"or":[{"state":"open"}]},{"priority":"high"}]} Defensive patterns
Strategy: validation
Validate before calling
def assert_no_operator_field_mix(node):
op_keys = [k for k in node if isinstance(k, str) and k.lower() in ('or','and','not')]
if op_keys and len(node) > 1:
raise ValueError(f'operator {op_keys[0]} cannot share a node with field keys') Type guard
function operatorNodeIsPure(node) {
const keys = Object.keys(node);
const op = keys.find(k => ['or','and','not'].includes(k.toLowerCase()));
return !op || keys.length === 1;
} Prevention
- Treat operator nodes as structural wrappers — never update() field keys into them.
- Place field filters inside a child of the operator.
When it happens
Trigger: GET .../?filters={"or":[{"state":"open"}],"priority":"high"} ; GET .../?filters={"state":"open","not":{"priority":"low"}}.
Common situations: Adding a quick field filter to an existing operator object via spread/merge; misunderstanding that fields cannot ride alongside the operator; legacy converter that flattens fields into the operator node.
Related errors
- invalid_filter_node
- empty_filter_object
- multiple_logical_operators
- invalid_operator_children
- invalid_operator_child_type
AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12).
Data as JSON: /api/errors/f7a7430af790cc32.
Report an issue: GitHub.