mem0ai/mem0 · error · Error
Neptune Analytics cannot negate this filter shape for vector
Error message
Neptune Analytics cannot negate this filter shape for vector search.
What it means
negateVertexFilter() implements De Morgan transformation only for shapes it can invert: andAll/orAll compositions, in, and notIn. If a $not wraps a filter shape it cannot negate (e.g. startsWith, contains, or a combined eq shape with no inverse mapping), it throws rather than emitting a filter with incorrect semantics.
Source
Thrown at mem0-ts/src/oss/src/vector_stores/neptune_analytics.ts:732
if (filter.lessThanOrEquals) {
return {
greaterThan: filter.lessThanOrEquals,
};
}
if (filter.in) {
return {
notIn: filter.in,
};
}
if (filter.notIn) {
return {
in: filter.notIn,
};
}
throw new Error(
"Neptune Analytics cannot negate this filter shape for vector search.",
);
}
private buildWhereClause(
filters?: SearchFilters,
startIndex: number = 1,
): WhereClauseResult {
const clauses: string[] = [];
const parameters: Record<string, any> = {};
let nextIndex = startIndex;
for (const [key, value] of Object.entries(filters || {})) {
if (value === undefined) {
continue;
}
if (key === "$and" || key === "$or") {View on GitHub (pinned to 001c235229)
Solutions
- Move the negation to supported leaves: negate equality ({ field: 'x' } under $not) or membership (in).
- Post-filter client-side: fetch with the positive filter removed, then exclude matching payloads in JS.
- Restructure: use notIn lists instead of $not over startsWith/contains.
Example fix
// before
store.search(q, 20, { $not: [{ name: { startsWith: 'test-' } }] }); // throws
// after
const res = await store.search(q, 20);
const filtered = res.filter(r => !r.payload?.name?.startsWith('test-')); Defensive patterns
Strategy: fallback
Validate before calling
function isNegatableShape(node: any): boolean {
if (Array.isArray(node.$and) || Array.isArray(node.$or)) return node.$and?.every(isNegatableShape) ?? node.$or?.every(isNegatableShape) ?? true;
const v = Object.values(node)[0];
if (v && typeof v === 'object' && !Array.isArray(v)) {
const op = Object.keys(v)[0];
return op === 'in' || op === 'notIn' || op === 'eq'; // only these have inverses
}
return true; // plain equality is negatable
} Type guard
type NegatableFilter =
| { in: { property: string; value: (string | number)[] } }
| { notIn: { property: string; value: (string | number)[] } }
| { andAll: NegatableFilter[] }
| { orAll: NegatableFilter[] }; Try / catch
try { results = await store.search(q, k, filters); }
catch (e) {
if (e instanceof Error && e.message.includes('cannot negate this filter shape')) {
// fallback: search without the $not clause, exclude matches client-side
const positive = removeNotClauses(filters);
const wide = await store.search(q, k, positive);
results = applyNotClientSide(wide, filters.$not);
} else throw e;
} Prevention
- Only negate in/notIn/equality leaves under $not; startsWith/contains have no Neptune inverse.
- Prefer notIn lists over $not of complex shapes.
- Test every filter tree shape you generate against the Neptune provider in CI.
When it happens
Trigger: { $not: [{ name: { startsWith: 'test-' } }] } or { $not: [{ data: { contains: 'x' } }] } on the neptune-analytics provider; nested $not inside $and/$or trees where the inner entries hit the unhandled shapes.
Common situations: Exclusion filters for prefix or substring matching; machine-generated filter trees that wrap arbitrary leaves in $not.
Related errors
- Neptune Analytics vector search does not support property-ex
- Neptune Analytics vector search does not support case-insens
- Unsupported Neptune Analytics filter operator: ${operator}
- ${key} filter value must be an array.
- $not filter value must be an array.
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/1e920c48afbc6e55.
Report an issue: GitHub.