n8n-io/n8n · error
Invalid Qdrant point id "${id}": Qdrant requires ids to be a
Error message
Invalid Qdrant point id "${id}": Qdrant requires ids to be a UUID or a canonical unsigned integer. What it means
Thrown by toPointId in the Qdrant backend when a record id is neither a UUID (hyphenated, simple, urn, or braced forms accepted, matching Qdrant's Rust parser) nor a canonical unsigned integer. Qdrant rejects arbitrary string ids with a 400, so this validates first and surfaces a clear message. Note: VectorStore.addDocuments generates UUIDs via crypto.randomUUID() by default, so this only fires when the caller supplies a custom doc.id.
Source
Thrown at packages/@n8n/agents/src/vector-stores/qdrant.ts:131
if (!this.client) {
const { QdrantClient: QdrantClientCtor } = await import('@qdrant/js-client-rest');
this.client = new QdrantClientCtor({
url: this.constructorOptions.url,
apiKey: this.constructorOptions.apiKey,
});
}
return this.client;
}
}
/** Qdrant only accepts UUID or unsigned-integer point ids. */
function toPointId(id: string): string | number {
if (UUID_PATTERN.test(id)) return id;
const numeric = Number(id);
if (UNSIGNED_INT_PATTERN.test(id) && Number.isSafeInteger(numeric) && String(numeric) === id) {
return numeric;
}
throw new Error(
`Invalid Qdrant point id "${id}": Qdrant requires ids to be a UUID or a canonical unsigned integer.`,
);
}
function toQueryResult(point: Schemas['ScoredPoint']): VectorQueryResult {
const payload = (point.payload ?? {}) as unknown as QdrantPayload;
return {
id: String(point.id),
content: payload.content,
metadata: payload.metadata ?? {},
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 };View on GitHub (pinned to 5ac6606e81)
Solutions
- Let VectorStore.addDocuments auto-generate UUIDs (omit doc.id) — recommended for Qdrant.
- If you need stable ids, generate and store UUIDs (crypto.randomUUID()) and use those as the canonical id everywhere.
- For numeric ids, pass a canonical unsigned integer string with no leading zeros or sign (e.g. '5', not '05' or '+5').
- If you must keep opaque string ids, choose a different backend (PgVectorStore/SupabaseVectorStore accept arbitrary text ids).
Example fix
// before — Qdrant rejects the custom slug id
await store.addDocuments([{ id: 'user_123', content: 'doc', metadata: {} }]);
// after — let the store mint UUIDs, keep your slug in metadata
await store.addDocuments([{ content: 'doc', metadata: { slug: 'user_123' } }]); Defensive patterns
Strategy: validation
Validate before calling
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
const UINT = /^\d+$/;
function isQdrantSafeId(id: string): boolean {
if (UUID.test(id)) return true;
const n = Number(id);
return UINT.test(id) && Number.isSafeInteger(n) && String(n) === id;
}
if (doc.id && !isQdrantSafeId(doc.id)) {
throw new Error(`Refusing id "${doc.id}" for Qdrant; use a UUID or unsigned int`);
} Type guard
function isQdrantId(id: string): boolean {
return isQdrantSafeId(id); // see validationCode
} Prevention
- For Qdrant, let VectorStore.addDocuments mint UUIDs (omit doc.id) — UUIDs are always accepted.
- If you need stable ids, generate and persist UUIDs and use them as the canonical id everywhere.
- If you must keep opaque string ids, choose PgVectorStore or SupabaseVectorStore, which accept arbitrary text ids.
When it happens
Trigger: Upserting a VectorDocument with `id: 'user_123'`, `id: 'doc:abc'`, `id: '-5'`, `id: '3.0'` (non-canonical), or `id: '0123'` (leading zero — fails the `String(numeric) === id` canonical check); deleting by such ids.
Common situations: Using business-domain string ids (slugs, SKUs, composite keys) instead of UUIDs; migrating ids from another store; integer ids with leading zeros or signs; truncating/padding ids.
Related errors
- Filter operator "${operator}" on key "${key}" does not suppo
- Filter operator "${operator}" on key "${key}" requires a non
- Filter operator "${operator}" on key "${key}" requires all a
- Invalid filter operator "${operator}" for key "${key}". Supp
- Filter operator "${operator}" on key "${key}" requires a non
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/a7b0949f93df0905.
Report an issue: GitHub.