mem0ai/mem0 · error · Error
${key} filter value must be an array.
Error message
${key} filter value must be an array. What it means
When translating mem0 filters to OpenSearch bool queries, the logical combinators AND/OR/NOT must each hold an array of nested filter objects so they can be flat-mapped into sub-clauses. A non-array value (single object or scalar) cannot be expanded, so the builder throws naming the offending combinator key.
Source
Thrown at mem0-ts/src/oss/src/vector_stores/opensearch.ts:518
const normalized: Record<string, any> = {};
for (const [key, value] of Object.entries(filters)) {
normalized[KEY_MAP[key] || key] = value;
}
return Object.entries(normalized)
.map(([key, value]) => this.buildFilterClause(key, value))
.filter((clause): clause is Record<string, any> => Boolean(clause));
}
private buildFilterClause(
key: string,
value: any,
): Record<string, any> | null {
if (value === null || value === undefined) return null;
if (key === "AND" || key === "OR" || key === "NOT") {
if (!Array.isArray(value)) {
throw new Error(`${key} filter value must be an array.`);
}
const clauses = value
.flatMap((filter) => this.buildFilterClauses(filter))
.filter(Boolean);
if (clauses.length === 0) return null;
if (key === "AND") {
return { bool: { filter: clauses } };
}
if (key === "OR") {
return { bool: { should: clauses, minimum_should_match: 1 } };
}
return { bool: { must_not: clauses } };
}
if (value === "*") {View on GitHub (pinned to 001c235229)
Solutions
- Wrap combinator values in arrays: { AND: [ { user_id: 'a' } ] }, { OR: [ ... ] }, { NOT: [ ... ] }.
- If porting from $and/$or/$not style, also rename keys to uppercase AND/OR/NOT for this backend.
- Centralize filter construction in one helper that always emits arrays for combinators.
Example fix
// before
{ NOT: { run_id: 'old' } }
// after
{ NOT: [ { run_id: 'old' } ] } Defensive patterns
Strategy: validation
Validate before calling
for (const k of ['AND', 'OR', 'NOT']) {
if (k in filters && !Array.isArray((filters as any)[k])) {
(filters as any)[k] = [(filters as any)[k]]; // normalize
}
} Type guard
const isClauseList = (v: unknown): v is Record<string, any>[] => Array.isArray(v) && v.every((e) => e && typeof e === 'object' && !Array.isArray(e));
Prevention
- Use uppercase AND/OR/NOT with array values on OpenSearch
- Convert $and/$or/$not to AND/OR/NOT when porting filters
- Test filters against a tiny fixture before production
When it happens
Trigger: Passing filters such as { AND: { user_id: 'a' } }, { OR: 'x' }, or { NOT: { run_id: 'y' } } to keywordSearch/vector search/list on the OpenSearch store.
Common situations: Filters authored for the Python SDK or Neptune backend using $and/$or/$not lowercase single objects and partially converted; dynamic filter assembly forgetting the array; JSON configs that drop single-element arrays.
Related errors
- Filter value for '${key}' must be an array.
- Top-level entity parameters [${invalidKeys.join(", ")}] are
- Invalid ${name}: cannot be empty or whitespace-only. Provide
- Invalid ${name}: cannot contain whitespace. Provide a valid
- AND filter value must be a list of filter dicts, got ${typeo
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/e675a3442cd83f11.
Report an issue: GitHub.