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
- Pass at least one identifier: memory.add(text, { userId: 'u1' })
- If keys come from config, verify they are camelCase (userId, agentId, runId) — snake_case belongs in filters, not the top-level options
- 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
- Derive the scope options from one session object so an add() without scope is impossible
- Remember top-level config uses camelCase; snake_case keys belong inside filters
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
- messages array cannot contain only blank content. Provide at
- messages string cannot be empty. Provide non-empty content.
- 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/fdac40163e4553d3.
Report an issue: GitHub.