mem0ai/mem0 · error · Error
Filter value for ${key} must be str, int, float, or bool, go
Error message
Filter value for ${key} must be str, int, float, or bool, got ${Array.isArray(value) ? "array" : typeof value} What it means
buildFilter only renders string, number, and boolean filter values into the Mochow predicate string; any other type (array, object, null, undefined) reaches the final throw, naming the key and reporting 'array' for arrays or the JS typeof otherwise. Mochow's filter DSL as used here has no operator for containment, so array filters are unsupported rather than silently ignored.
Source
Thrown at mem0-ts/src/oss/src/vector_stores/baidu.ts:279
private buildFilter(filters: SearchFilters): string {
const conditions: string[] = [];
for (const [key, value] of Object.entries(filters)) {
if (!SAFE_FILTER_KEY.test(key)) {
throw new Error(`Invalid filter key: ${key}`);
}
if (typeof value === "string") {
conditions.push(`metadata["${key}"] = "${escapeFilterString(value)}"`);
continue;
}
if (typeof value === "number" || typeof value === "boolean") {
conditions.push(`metadata["${key}"] = ${value}`);
continue;
}
throw new Error(
`Filter value for ${key} must be str, int, float, or bool, got ${Array.isArray(value) ? "array" : typeof value}`,
);
}
return conditions.join(" AND ");
}
private filterOf(filters?: SearchFilters): string | undefined {
return filters && Object.keys(filters).length > 0
? this.buildFilter(filters)
: undefined;
}
private async pollTable(
client: MochowClient,
settled: (response: DescTableResponse) => boolean,
what: string,
): Promise<void> {View on GitHub (pinned to 001c235229)
Solutions
- Replace array filters with a single scalar value, or issue one search per array element and merge results.
- Strip null/undefined entries from the filter object before calling search().
- Keep SearchFilters values to string | number | boolean by design.
Example fix
// before
const filters = { user_id: ['u1', 'u2'], run_id: null };
// after
const filters = { user_id: 'u1' };
// or merge searches per element Defensive patterns
Strategy: type-guard
Validate before calling
function normalizeFilters(f: Record<string, unknown> = {}) {
const out: Record<string, string | number | boolean> = {};
for (const [k, v] of Object.entries(f)) {
if (v == null) continue; // drop null/undefined
if (['string','number','boolean'].includes(typeof v)) out[k] = v as any;
else if (Array.isArray(v)) v.forEach(x => { if (x != null) out[k] = x as any; }); // last-wins; or fan out
else throw new Error(`Unsupported filter value for ${k}`);
}
return out;
} Type guard
type ScalarFilterValue = string | number | boolean; const isScalarFilterValue = (v: unknown): v is ScalarFilterValue => ['string','number','boolean'].includes(typeof v);
Try / catch
try { await memory.search(q, filters) } catch (e) { if (e instanceof Error && /Filter value for .* must be str, int, float, or bool/.test(e.message)) { return memory.search(q, normalizeFilters(filters)); } throw e; } Prevention
- Type SearchFilters values as string | number | boolean in your own code.
- Strip null/undefined and expand arrays into per-value searches before calling search().
When it happens
Trigger: memory.search('q', { user_id: ['u1', 'u2'] }) (IN-filter); filters { run_id: null } or { agent_id: { $in: [...] } } (Mongo-style syntax leaking through).
Common situations: Porting filters from a store that supports arrays (Qdrant match-any); forgetting that null/undefined values should be omitted from the filter object entirely.
Related errors
- Invalid filter key: ${key}
- Filter value for {key!r} must be str, int, float, or bool, g
- filters must contain at least one of: user_id, agent_id, run
- Unsupported metadata filter operator: {operator}
- AND operator requires a list of conditions
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/ca9bac4947b3c8a6.
Report an issue: GitHub.