mem0ai/mem0 · error · Error
$not filter requires a non-empty list
Error message
$not filter requires a non-empty list
What it means
$not in S3 Vectors filters must be a non-empty array of sub-filter objects. An empty or non-array value throws before translation, since negating nothing has no defined behavior in the store's filter model.
Source
Thrown at mem0-ts/src/oss/src/vector_stores/s3_vectors.ts:536
(entry) => !this.isAlwaysFalseFilter(entry),
);
if (viableEntries.length === 0) {
return { [ALWAYS_FALSE_FILTER_KEY]: true };
}
clauses.push(
viableEntries.length === 1
? viableEntries[0]
: { [key]: viableEntries },
);
continue;
}
clauses.push(entries.length === 1 ? entries[0] : { [key]: entries });
continue;
}
if (key === "$not") {
if (!Array.isArray(value) || value.length === 0) {
throw new Error("$not filter requires a non-empty list");
}
const normalizedEntries = value.map((entry) =>
this.convertFilterNode(entry),
);
if (normalizedEntries.some((entry) => this.isNoOpFilter(entry))) {
return { [ALWAYS_FALSE_FILTER_KEY]: true };
}
const negated = normalizedEntries.filter(
(entry) => !this.isAlwaysFalseFilter(entry),
);
if (negated.length === 0) {
continue;
}
const negatedFilters = negated.map((entry) => this.negateFilter(entry));
clauses.push(
negatedFilters.length === 1
? negatedFilters[0]View on GitHub (pinned to 001c235229)
Solutions
- Drop the $not key when the exclusion list is empty
- Build conditionally: const filters = exclusions.length ? { $not: exclusions } : {}
- Reject empty $not arrays when validating external filter payloads
Example fix
// before
const filters = { $not: excludeTags.map(t => ({ tag: { eq: t } })) };
// after
const excl = excludeTags.map(t => ({ tag: { eq: t } }));
const filters = excl.length > 0 ? { $not: excl } : {}; Defensive patterns
Strategy: validation
Validate before calling
function buildNotFilter(exclusions: any[]): any | undefined {
const list = exclusions.filter(e => e && typeof e === 'object');
return list.length > 0 ? { $not: list } : undefined;
}
const filters = buildNotFilter(excludeList) ?? {}; Type guard
const isNonEmptyNotList = (v: unknown): v is Record<string, any>[] => Array.isArray(v) && v.length > 0 && v.every(i => i && typeof i === 'object' && !Array.isArray(i));
Try / catch
try { await vs.search(vec, { filters }); } catch (e) { if (e instanceof Error && e.message === '$not filter requires a non-empty list') { /* omit $not, retry */ } throw e; } Prevention
- Treat an empty exclusion list as 'no filter', not as an empty $not wrapper
- Compose exclusion filters only after filtering out null/undefined entries
- Cover empty-exclusion cases in filter-builder tests
When it happens
Trigger: filters: { $not: [] }, { $not: null }, or { $not: excludeConditions } where excludeConditions was filtered down to nothing.
Common situations: Exclusion lists computed at runtime that occasionally end up empty; merging user filter JSON with optional exclusion arrays; copy-paste of $and-style wrappers where empties slipped through.
Related errors
- ${key} filter requires a non-empty list
- ${key} filter value must be a list of filter dicts, got ${ty
- ${key} filter list item at index ${i} must be a dict, got ${
- Invalid filter key '${key}': only letters, digits, and under
- Unsupported filter operator: ${op}
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/5b2b3fb0f12abc64.
Report an issue: GitHub.