n8n-io/n8n · error

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

Error message

Filter operator "${operator}" on key "${key}" requires all array elements to be strings or all to be integers: Qdrant match does not support mixed-type or float values.

What it means

Thrown by buildCondition in the Qdrant backend for `in`/`nin` conditions when the array is neither all-strings nor all-integers (e.g. mixed `['a', 5]`, or contains floats like `[1.5, 2.5]`, or contains booleans). Qdrant's `match.any` requires a homogeneous array of strings or integers; mixed-type or float arrays are rejected before the request. Operator and key are named.

Source

Thrown at packages/@n8n/agents/src/vector-stores/qdrant.ts:177

			if (typeof value === 'number' && !Number.isInteger(value)) {
				throw new Error(
					`Filter operator "${operator}" on key "${key}" does not support float values: Qdrant match only supports strings, integers, and booleans.`,
				);
			}
			const match: Schemas['Condition'] = { key: payloadKey, match: { value } };
			return operator === 'eq' ? match : { must_not: [match] };
		}
		case 'in':
		case 'nin': {
			if (!Array.isArray(value) || value.length === 0) {
				throw new Error(
					`Filter operator "${operator}" on key "${key}" requires a non-empty array value.`,
				);
			}
			const allStrings = value.every((v) => typeof v === 'string');
			const allIntegers = value.every((v) => typeof v === 'number' && Number.isInteger(v));
			if (!allStrings && !allIntegers) {
				throw new Error(
					`Filter operator "${operator}" on key "${key}" requires all array elements to be strings or all to be integers: Qdrant match does not support mixed-type or float values.`,
				);
			}
			// eslint-disable-next-line id-denylist -- `any` is Qdrant's match-schema field name
			const anyCondition: Schemas['Condition'] = { key: payloadKey, match: { any: value } };
			return operator === 'in' ? anyCondition : { must_not: [anyCondition] };
		}
		default:
			throw new Error(`Unsupported filter operator: "${String(operator)}"`);
	}
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Normalize every element to the same type before building the condition — typically map all to strings (`value.map(String)`).
  2. Split mixed-type filters into separate homogeneous `in` conditions combined with `or`.
  3. Drop floats from in/nin arrays (Qdrant match cannot represent them); bucket them into strings if filtering is needed.

Example fix

// before — mixed types
await store.search('q', {
  filter: { conditions: [{ key: 'k', operator: 'in', value: ['a', 5] }] },
});

// after — homogeneous strings
await store.search('q', {
  filter: { conditions: [{ key: 'k', operator: 'in', value: ['a', '5'] }] },
});
Defensive patterns

Strategy: type-guard

Validate before calling

function homogenizeQdrantInValue(key: string, value: unknown[]): (string | number)[] {
  const allStrings = value.every((v) => typeof v === 'string');
  const allInts = value.every((v) => typeof v === 'number' && Number.isInteger(v));
  if (allStrings || allInts) return value as (string | number)[];
  // Fall back: stringify every element so Qdrant match.any accepts it.
  return value.map((v) => String(v));
}

const c = { key, operator: 'in' as const, value: homogenizeQdrantInValue(key, rawList) };

Type guard

function isHomogeneousQdrantArray(v: unknown): v is (string | number)[] {
  if (!Array.isArray(v) || v.length === 0) return false;
  const allStrings = v.every((x) => typeof x === 'string');
  const allInts = v.every((x) => typeof x === 'number' && Number.isInteger(x));
  return allStrings || allInts;
}

if (!isHomogeneousQdrantArray(c.value)) c.value = c.value.map(String);

Try / catch

try {
  await store.search('q', { filter: { conditions, combineWith: 'and' } });
} catch (err) {
  if (err instanceof Error && /requires all array elements to be strings/.test(err.message)) {
    // homogenize to strings and retry once
    conditions = conditions.map((c) =>
      (c.operator === 'in' || c.operator === 'nin') && Array.isArray(c.value)
        ? { ...c, value: c.value.map(String) }
        : c,
    );
    await store.search('q', { filter: { conditions, combineWith: 'and' } });
  } else throw err;
}

Prevention

When it happens

Trigger: `{ key: 'k', operator: 'in', value: ['a', 1] }` (mixed); `{ key: 'k', operator: 'in', value: [1.1, 2.2] }` (floats); `{ key: 'k', operator: 'in', value: ['a', true] }` (string+boolean); a heterogeneous list built from user input without normalization.

Common situations: Unioning filter values from multiple sources with different types; numeric ids mixed with code strings; floats from computed metadata; booleans accidentally included.

Related errors


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