n8n-io/n8n · error · Error

Filter operator "${operator}" on key "${key}" requires a non

Error message

Filter operator "${operator}" on key "${key}" requires a non-empty array value.

What it means

For the 'in' and 'nin' set-membership operators, assertValidCondition requires the value to be a non-empty array. An empty array would make the filter a no-op or match nothing depending on backend semantics; a non-array value is a type mismatch. The validator rejects both cases rather than coercing, so silent no-ops never reach the vector store.

Source

Thrown at packages/@n8n/agents/src/sdk/vector-store-filter.ts:50

/** Validates operator/value pairing per condition; throws rather than silently ignoring a bad filter. */
export function assertValidFilter(filter: VectorFilter): void {
	for (const condition of filter.conditions) {
		assertValidCondition(condition);
	}
}

function assertValidCondition(condition: FilterCondition): void {
	const { key, operator, value } = condition;

	if (!(FILTER_OPERATORS as readonly string[]).includes(operator)) {
		throw new Error(
			`Invalid filter operator "${operator}" for key "${key}". Supported operators: ${FILTER_OPERATORS.join(', ')}`,
		);
	}

	if (operator === 'in' || operator === 'nin') {
		if (!Array.isArray(value) || value.length === 0) {
			throw new Error(
				`Filter operator "${operator}" on key "${key}" requires a non-empty array value.`,
			);
		}
		if (value.some((v) => typeof v !== 'string' && typeof v !== 'number')) {
			throw new Error(
				`Filter operator "${operator}" on key "${key}" requires array elements to be strings or numbers.`,
			);
		}
		return;
	}

	// eq, ne
	if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') {
		throw new Error(
			`Filter operator "${operator}" on key "${key}" requires a string, number, or boolean value.`,
		);
	}
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Ensure the value is an array with at least one element: value: ['x', 'y'] for 'in'.
  2. If the candidate array may be empty (e.g. user selected nothing), short-circuit and skip the search or omit that condition rather than passing value: [].
  3. Use 'eq' with a scalar value instead of 'in' when you only have a single value.

Example fix

// before
store.search('q', {
  filter: { conditions: [{ key: 'tag', operator: 'in', value: [] }], combineWith: 'and' },
}); // throws

// after — guard the empty case
const tags = selectedTags.length
  ? [{ key: 'tag', operator: 'in', value: selectedTags }]
  : [];
store.search('q', { filter: { conditions: tags, combineWith: 'and' } });
Defensive patterns

Strategy: validation

Validate before calling

function inCondition(key: string, values: unknown[]) {
  if (!Array.isArray(values) || values.length === 0) {
    throw new Error(`'in' filter on ${key} requires a non-empty array`);
  }
  return { key, operator: 'in' as const, value: values };
}

Type guard

function isNonEmptyArray<T>(v: unknown): v is [T, ...T[]] {
  return Array.isArray(v) && v.length > 0;
}

Prevention

When it happens

Trigger: Calling search with filter: { conditions: [{ key: 'tag', operator: 'in', value: [] }] } (empty array) or { ... operator: 'in', value: 'x' } (scalar instead of array). Also triggered by arrays that exist but have length 0 due to upstream filtering producing no candidates.

Common situations: Passing a dynamically-built array that ended up empty after filtering; confusing 'in' (set) with 'eq' (scalar); copying a value from an eq condition into an in condition without wrapping in an array.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/4fbeb2db5e90daa5. Report an issue: GitHub.