n8n-io/n8n · error

Filter operator "${operator}" on key "${key}" does not suppo

Error message

Filter operator "${operator}" on key "${key}" does not support float values: Qdrant match only supports strings, integers, and booleans.

What it means

Thrown by buildCondition in the Qdrant backend when an `eq`/`ne` condition's value is a non-integer number (a float). Qdrant's `match` filter only accepts strings, integers, and booleans — floats have no exact representation in its match index, so they are rejected before the request. Operator and key are named in the message.

Source

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

		score: point.score,
	};
}

/** Negations are expressed as nested `must_not` filters so both `and`/`or` combinators work uniformly. */
function buildQdrantFilter(filter: VectorFilter): Schemas['Filter'] {
	const conditions = filter.conditions.map(buildCondition);
	return filter.combineWith === 'or' ? { should: conditions } : { must: conditions };
}

function buildCondition(condition: FilterCondition): Schemas['Condition'] {
	const { key, operator, value } = condition;
	const payloadKey = `metadata.${key}`;

	switch (operator) {
		case 'eq':
		case 'ne': {
			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.`,

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Don't use eq/ne for float metadata — Qdrant match cannot represent it. Store floats only for retrieval, not exact-match filtering.
  2. If exact filtering is required, store a coarser integer/string representation (e.g. price_cents as integer, or a price bucket string) and filter on that.
  3. For range semantics, note the SDK filter API has no range operator; consider a backend that supports it (Postgres with jsonb) or pre-bucket the value.

Example fix

// before
await store.search('q', {
  filter: { conditions: [{ key: 'price', operator: 'eq', value: 9.99 }] },
});

// after — store and filter on an integer/string bucket instead
await store.addDocuments([
  { content: 'item', metadata: { price_cents: 999, price_band: '0-10' } },
]);
await store.search('q', {
  filter: { conditions: [{ key: 'price_band', operator: 'eq', value: '0-10' }] },
});
Defensive patterns

Strategy: validation

Validate before calling

function assertQdrantEqValue(key: string, value: unknown): void {
  if (typeof value === 'number' && !Number.isInteger(value)) {
    throw new Error(`Qdrant eq/ne on "${key}" cannot take a float (${value}); use a string/int/bool bucket`);
  }
}

conditions.forEach((c) => {
  if (c.operator === 'eq' || c.operator === 'ne') assertQdrantEqValue(c.key, c.value);
});

Type guard

function isQdrantMatchValue(v: unknown): v is string | number | boolean {
  return typeof v === 'string' || typeof v === 'boolean' || (typeof v === 'number' && Number.isInteger(v));
}

Prevention

When it happens

Trigger: Filtering with `{ key: 'price', operator: 'eq', value: 9.99 }`; `{ key: 'score', operator: 'ne', value: 1.5 }`; any numeric metadata that is a float used in an eq/ne filter.

Common situations: Numeric metadata stored as floats (price, rating, geo coords) and filtered with eq/ne; reading filter values from JSON config that parses to floats; comparing against a computed float.

Related errors


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