mem0ai/mem0 · error

filters must contain at least one of: user_id, agent_id, run

Error message

filters must contain at least one of: user_id, agent_id, run_id. Example: filters: { user_id: 'u1' }

What it means

Thrown by Memory.search() after filter processing when the effective filters contain none of user_id, agent_id, or run_id. Search is scoped per entity in the OSS SDK, so an unscoped query is rejected rather than run across all users' memories. Note the check is on snake_case keys — top-level camelCase config keys are converted first, but arbitrary filter keys are not.

Source

Thrown at mem0-ts/src/oss/src/memory/index.ts:1415

      for (const fk of Object.keys(effectiveFilters)) {
        if (
          !["AND", "OR", "NOT", "user_id", "agent_id", "run_id"].includes(fk) &&
          typeof effectiveFilters[fk] === "object" &&
          effectiveFilters[fk] !== null
        ) {
          delete effectiveFilters[fk];
        }
      }
      effectiveFilters = { ...effectiveFilters, ...processedFilters };
    }

    // Validate filters contains at least one entity ID (snake_case)
    if (
      !effectiveFilters.user_id &&
      !effectiveFilters.agent_id &&
      !effectiveFilters.run_id
    ) {
      throw new Error(
        "filters must contain at least one of: user_id, agent_id, run_id. " +
          "Example: filters: { user_id: 'u1' }",
      );
    }

    const searchStartMs = Date.now();

    // Step 1: Preprocess query
    const queryLemmatized = lemmatizeForBm25(query);
    const queryEntities = extractEntities(query);

    // Step 2: Embed query
    const queryEmbedding = await this.embedder.embed(query, "search");

    // Step 3: Semantic search (over-fetch for scoring pool)
    const internalLimit = Math.max(topK * 4, 60);
    const semanticResults = await this.vectorStore.search(
      queryEmbedding,

View on GitHub (pinned to 001c235229)

Solutions

  1. Include an entity key in filters: memory.search(q, { filters: { user_id: 'u1' } })
  2. Use snake_case keys inside filters (user_id, agent_id, run_id); camelCase belongs in the top-level config which is converted for you
  3. Combine entity scope with metadata filters: { user_id: 'u1', AND: [{ category: { equals: 'pref' } }] }

Example fix

// before
await memory.search('preferences', { filters: { userId: 'alice' } });

// after
await memory.search('preferences', { filters: { user_id: 'alice' } });
Defensive patterns

Strategy: type-guard

Validate before calling

function scopedFilters(f: Record<string, unknown> = {}) {
  if (!f.user_id && !f.agent_id && !f.run_id) {
    throw new Error('search requires user_id, agent_id, or run_id');
  }
  return f;
}

Type guard

const isEntityScoped = (
  f?: Partial<Record<'user_id' | 'agent_id' | 'run_id', string>>,
): boolean => Boolean(f && (f.user_id || f.agent_id || f.run_id));

Prevention

When it happens

Trigger: Calling memory.search('query', { filters: {} }), or passing filters with only non-entity keys like { category: 'prefs' }, or passing camelCase entity keys directly inside filters ({ userId: 'u1' }) so the snake_case check misses them.

Common situations: Assuming search() without filters searches everything (it does not — use entity-scoped search); mixing camelCase into the filters object; building filters dynamically so the entity key can be absent.

Related errors


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