{"record":{"id":"b32d600f748d394c","repo":"n8n-io/n8n","slug":"filter-operator-operator-on-key-key-requ-b32d60","errorCode":null,"errorMessage":"Filter operator \"${operator}\" on key \"${key}\" requires a non-empty array value.","messagePattern":"Filter operator \"(.+?)\" on key \"(.+?)\" requires a non-empty array value\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/@n8n/agents/src/vector-stores/supabase.ts","lineNumber":247,"sourceCode":"\t\t\tassertNonEmptyArray(operator, key, value);\n\t\t\treturn `and(${value.map((candidate) => `metadata.not.cs.${quoteOrValue(containmentJson(key, candidate))}`).join(',')})`;\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported filter operator: \"${String(operator)}\"`);\n\t}\n}\n\nfunction containmentJson(key: string, value: unknown): string {\n\treturn JSON.stringify({ [key]: value });\n}\n\nfunction assertNonEmptyArray(\n\toperator: string,\n\tkey: string,\n\tvalue: unknown,\n): asserts value is Array<string | number> {\n\tif (!Array.isArray(value) || value.length === 0) {\n\t\tthrow new Error(\n\t\t\t`Filter operator \"${operator}\" on key \"${key}\" requires a non-empty array value.`,\n\t\t);\n\t}\n}\n\n/** PostgREST logic-string values containing reserved characters must be double-quoted. */\nfunction quoteOrValue(value: string): string {\n\treturn `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')}\"`;\n}\n","sourceCodeStart":229,"sourceCodeEnd":257,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/agents/src/vector-stores/supabase.ts#L229-L257","documentation":"The Supabase vector-store adapter builds PostgREST containment (`cs`) logic strings for the `in` and `nin` metadata filter operators. Those operators mean 'metadata contains any of these values', which is only meaningful for a non-empty set, so assertNonEmptyArray rejects undefined/null/scalar/[] values before they produce a malformed or vacuous query. It is a hard precondition on the filter shape, not a runtime/network failure.","triggerScenarios":"Calling similarity search on the Supabase vector store with a filter condition whose operator is `in` or `nin` and whose value is undefined, null, a string, a number, or an empty array `[]` (see the `in`/`nin` cases in toAndLogicTerm/toOrLogicTerm at supabase.ts:225/229/204, which both call assertNonEmptyArray before reducing over `value`).","commonSituations":"An upstream expression evaluates to undefined and is passed straight into the filter; the AI agent/LLM emits a single scalar instead of a list for a list-typed tool argument; a workflow maps a missing JSON field into value; the caller reuses an `eq`-style single value with the `in` operator.","solutions":["Pass an array with at least one element: { key: 'tag', operator: 'in', value: ['red','blue'] }.","If value is dynamic, validate before calling: skip the filter, or fall back to `eq`, when the array is empty — do not pass `value ?? []` to `in`/`nin`.","Coerce single scalars into one-element arrays at the boundary that builds the filter."],"exampleFix":"// before\n{ key: 'tag', operator: 'in', value: maybeTags } // maybeTags may be undefined\n\n// after\nconst tags = Array.isArray(maybeTags) && maybeTags.length\n  ? maybeTags\n  : null;\nconst filter = tags ? { key: 'tag', operator: 'in', value: tags } : undefined;","handlingStrategy":"validation","validationCode":"function isNonEmptyStringArray(v: unknown): v is Array<string | number> {\n  return Array.isArray(v) && v.length > 0 && v.every((x) => typeof x === 'string' || typeof x === 'number');\n}\n// before calling the vector store:\nfor (const c of filter.conditions) {\n  if ((c.operator === 'in' || c.operator === 'nin') && !isNonEmptyStringArray(c.value)) {\n    throw new Error(`filter '${c.key}' needs a non-empty array`);\n  }\n}","typeGuard":"function isNonEmptyArray(v: unknown): v is Array<string | number> {\n  return Array.isArray(v) && v.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Centralize filter construction in one builder that enforces the in/nin-requires-array rule.","At the AI-tool schema layer, mark list-typed params as required and minItems 1.","Unit-test the vector-store filter path with undefined/empty/array inputs."],"tags":["vector-store","supabase","filter","validation","postgrest"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}