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
- Normalize every element to the same type before building the condition — typically map all to strings (`value.map(String)`).
- Split mixed-type filters into separate homogeneous `in` conditions combined with `or`.
- 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
- Normalize in/nin arrays to one type (usually all strings) before building the condition.
- Never mix strings and numbers, and never include floats or booleans, in a Qdrant in/nin value.
- Centralize Qdrant filter construction behind a homogenizing helper.
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
- Filter operator "${operator}" on key "${key}" requires array
- Filter operator "${operator}" on key "${key}" requires a str
- Filter operator "${operator}" on key "${key}" does not suppo
- Filter operator "${operator}" on key "${key}" requires a non
- Invalid filter operator "${operator}" for key "${key}". Supp
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/6d63d1d3660ca1fe.
Report an issue: GitHub.