mem0ai/mem0 · error

One of the filters: userId, agentId or runId is required!

Error message

One of the filters: userId, agentId or runId is required!

What it means

Thrown by Memory.add() when none of the config fields userId, agentId, or runId is set. Mem0 scopes every memory to at least one entity (user, agent, or run) so it can filter later; an unscoped write would be unreachable by search/getAll, which both require the same filters. The check runs after camelCase params are converted to snake_case filters.

Source

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

    const userId = validateAndTrimEntityId(config.userId, "userId");
    const agentId = validateAndTrimEntityId(config.agentId, "agentId");
    const runId = validateAndTrimEntityId(config.runId, "runId");

    // Convert camelCase entity params to snake_case for storage (matches API and search/getAll filters)
    if (userId) filters.user_id = metadata.user_id = userId;
    if (agentId) filters.agent_id = metadata.agent_id = agentId;
    if (runId) filters.run_id = metadata.run_id = runId;
    if (filters.user_id) metadata.user_id = filters.user_id;
    if (filters.agent_id) metadata.agent_id = filters.agent_id;
    if (filters.run_id) metadata.run_id = filters.run_id;

    // Normalize expiration date into the stored metadata (round-trips via get()).
    if (config.expirationDate != null) {
      metadata.expiration_date = normalizeExpirationDate(config.expirationDate);
    }

    if (!filters.user_id && !filters.agent_id && !filters.run_id) {
      throw new Error(
        "One of the filters: userId, agentId or runId is required!",
      );
    }

    const parsedMessages = Array.isArray(messages)
      ? (messages as Message[])
      : [{ role: "user", content: messages }];

    const final_parsedMessages = await parse_vision_messages(parsedMessages);

    // Add to vector store
    const vectorStoreResult = await this.addToVectorStore(
      final_parsedMessages,
      metadata,
      filters,
      infer,
    );

View on GitHub (pinned to 001c235229)

Solutions

  1. Pass at least one identifier: memory.add(text, { userId: 'u1' })
  2. If keys come from config, verify they are camelCase (userId, agentId, runId) — snake_case belongs in filters, not the top-level options
  3. Default the scope in one place, e.g. const scope = { userId: session.userId ?? 'anonymous' }

Example fix

// before
await memory.add('User lives in Berlin');

// after
await memory.add('User lives in Berlin', { userId: 'alice' });
Defensive patterns

Strategy: validation

Validate before calling

const scope = { userId, agentId, runId };
if (!scope.userId && !scope.agentId && !scope.runId) {
  throw new Error('memory scope (userId/agentId/runId) is required');
}

Type guard

const hasScope = (c: { userId?: string; agentId?: string; runId?: string }) =>
  Boolean(c.userId || c.agentId || c.runId);

Prevention

When it happens

Trigger: Calling memory.add('text', {}) or memory.add('text', { userId: '', agentId: undefined }) so that filters.user_id, filters.agent_id, and filters.run_id are all falsy after assignment.

Common situations: Forgetting the second argument entirely; passing an options object with the wrong key names (e.g. user_id instead of userId in config, which is only accepted inside filters); entity IDs read from an unset env var or empty session.

Related errors


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