makeplane/plane · error · Error
AND group must contain at least one condition
Error message
AND group must contain at least one condition
What it means
Thrown while converting an external filter expression shaped as an AND group: the adapter looks up expression[LOGICAL_OPERATOR.AND] and requires it to be a non-empty array. An AND key whose value is [] or not an array (string, object) is rejected because an empty logical group has no semantics in the internal TFilterExpression tree.
Source
Thrown at packages/shared-state/src/store/work-item-filters/adapter.ts:77
}
const [property, operator, value] = conditionResult;
return createConditionNode({
property,
operator,
value,
});
}
// It's a logical group - check which type
const expressionKeys = Object.keys(expression);
if (LOGICAL_OPERATOR.AND in expression) {
const andExpression = expression as { [LOGICAL_OPERATOR.AND]: TWorkItemFilterExpressionData[] };
const andConditions = andExpression[LOGICAL_OPERATOR.AND];
if (!Array.isArray(andConditions) || andConditions.length === 0) {
throw new Error("AND group must contain at least one condition");
}
const convertedConditions = andConditions.map((item) => this._convertExpressionToInternal(item));
return createAndGroupNode(convertedConditions);
}
throw new Error(`Invalid expression: unknown structure with keys [${expressionKeys.join(", ")}]`);
}
/**
* Converts internal filter expression to external format
* @param internalFilter - The internal filter expression
* @returns External filter expression
*/
toExternal(internalFilter: TFilterExpression<TWorkItemFilterProperty>): TWorkItemFilterExpression {
if (!internalFilter) {
return {};
}View on GitHub (pinned to 1c8a60f858)
Solutions
- Normalize on save: if an AND group has zero children, prune the group (or skip persisting it) before serialization.
- On load, sanitize the payload by collapsing empty AND groups to an empty/no-filter state.
- Fix the UI to prevent saving a group with no conditions.
Example fix
// before
const saved = JSON.stringify(filterTree);
// after
function pruneEmptyGroups(node) {
if (node && typeof node === 'object' && Array.isArray(node.AND)) {
const kids = node.AND.map(pruneEmptyGroups).filter(Boolean);
return kids.length ? { AND: kids } : undefined;
}
return node;
}
const saved = JSON.stringify(pruneEmptyGroups(filterTree) ?? {}); Defensive patterns
Strategy: validation
Validate before calling
function normalizeAndGroup(node: any): any {
if (node && Array.isArray(node.AND)) {
const kids = node.AND.map(normalizeAndGroup).filter(Boolean);
if (kids.length === 0) return undefined;
return { AND: kids };
}
return node;
} Type guard
function isNonEmptyAndGroup(e: any): boolean {
return e && Array.isArray(e.AND) && e.AND.length > 0;
} Try / catch
try { adapter.toInternal(expr); } catch (e) {
if (/AND group must contain/.test((e as Error).message)) { expr = {}; /* retry as no-filter */ } else throw e;
} Prevention
- Prune empty groups before persist
- Block saving groups with zero conditions in the UI
- Sanitize imported/migrated filter payloads
When it happens
Trigger: Persisted payload like { AND: [] }; a UI that allows adding an AND group without children and then saves; corrupted/migrated data where the conditions array got stripped.
Common situations: User adds a group, removes all conditions, and the autosave writes { AND: [] }; import/migration tool that drops nested condition keys.
Related errors
- Invalid expression: empty or null data
- Invalid expression: unknown structure with keys [${expressio
- Invalid relative amount: ${amountStr}
- Unsupported time unit: ${unit}
- Invalid date format: {value}
AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12).
Data as JSON: /api/errors/ee8ee15c767e5454.
Report an issue: GitHub.