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

  1. Replace array filters with a single scalar value, or issue one search per array element and merge results.
  2. Strip null/undefined entries from the filter object before calling search().
  3. 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

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


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/ca9bac4947b3c8a6. Report an issue: GitHub.