n8n-io/n8n · error · Error

Filter operator "${operator}" on key "${key}" requires array

Error message

Filter operator "${operator}" on key "${key}" requires array elements to be strings or numbers.

What it means

For 'in' and 'nin' operators, after confirming the value is a non-empty array, assertValidCondition checks every element is a string or number. Mixed-type or object/null elements are rejected because vector store metadata indexes are scalar-typed; allowing them would produce backend-specific coercion or query failures. The check is per-element via Array.some.

Source

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

}

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.`,
		);
	}
}

function isNonEmptyArray(arr: string[]): arr is [string, ...string[]] {
	return arr.length > 0;
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Map array elements to strings or numbers before building the condition: value: items.map(i => i.id).
  2. Filter out null/undefined/object elements before constructing the filter.
  3. Serialize Dates to ISO strings (value.toISOString()) and other complex types to a string/number key.

Example fix

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

// after
store.search('q', {
  filter: { conditions: [{ key: 'cat', operator: 'in', value: items.map(i => i.id) }], combineWith: 'and' },
});
Defensive patterns

Strategy: type-guard

Validate before calling

function inCondition(key: string, values: unknown[]) {
  if (!values.every(v => typeof v === 'string' || typeof v === 'number')) {
    throw new Error(`'in' filter on ${key} requires string/number elements`);
  }
  return { key, operator: 'in' as const, value: values };
}

Type guard

function isScalarArray(v: unknown): v is (string | number)[] {
  return Array.isArray(v) && v.every(x => typeof x === 'string' || typeof x === 'number');
}

Prevention

When it happens

Trigger: Calling search with filter: { conditions: [{ key: 'tag', operator: 'in', value: ['x', null] }] } or value: [{ id: 1 }, { id: 2 }] (objects) or value: [true, false] (booleans not allowed in arrays).

Common situations: Passing an array of objects when only their id field matters; mixed types from loose user input; booleans or nulls leaking in from a form; serializing Date objects directly instead of as ISO strings.

Related errors


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