mem0ai/mem0 · warning · NodeOperationError

Mem0 memory add failed: ${(addResp.message as string) || 'un

Error message

Mem0 memory add failed: ${(addResp.message as string) || 'unknown error'}

What it means

GET /memories with no user_id/run_id/agent_id means 'list ALL memories in the store', which the server treats as an admin-only operation. If the caller is authenticated but their role is not admin (and auth is not via ADMIN_API_KEY/AUTH_DISABLED), the request is rejected with 403. Providing any single identifier scopes the query and avoids the check entirely.

Source

Thrown at integrations/n8n-nodes-mem0/nodes/Mem0/Mem0.node.ts:472

					// API requires at least one entity id — fail clearly instead of a raw 4xx.
					if (!body.user_id && !body.agent_id && !body.run_id && !body.app_id) {
						throw new NodeOperationError(
							this.getNode(),
							'Add requires at least one of User ID, Agent ID, Run ID, or App ID',
							{ itemIndex: i },
						);
					}

					const addResp = await request('POST', '/v3/memories/add/', body);
					const waitForCompletion = this.getNodeParameter('waitForCompletion', i, true) as boolean;
					const addStatus = addResp.status as string | undefined;
					const isTerminal = addStatus === 'SUCCEEDED' || addStatus === 'FAILED';

					// Add returns {event_id, status:PENDING|RUNNING}; poll until terminal when asked to wait.
					if (waitForCompletion && addResp.event_id && !isTerminal) {
						responseData = await pollEvent(request, addResp.event_id as string, this, i);
					} else if (addStatus === 'FAILED') {
						throw new NodeOperationError(
							this.getNode(),
							`Mem0 memory add failed: ${(addResp.message as string) || 'unknown error'}`,
							{ itemIndex: i },
						);
					} else {
						// If the response is already terminal, unwrap results; otherwise return as-is.
						responseData = Array.isArray(addResp.results)
							? (addResp.results as IDataObject[])
							: addResp;
					}
				} else if (operation === 'search') {
					const body: IDataObject = {
						query: this.getNodeParameter('query', i) as string,
						output_format: 'v1.1',
						top_k: this.getNodeParameter('limit', i, 50) as number,
					};
					body.filters = buildEntityFilters(
						{

View on GitHub (pinned to 001c235229)

Solutions

  1. Add at least one scope query parameter: GET /memories?user_id=alice (or agent_id/run_id).
  2. Or authenticate as an admin-role user / use ADMIN_API_KEY for the unscoped listing.
  3. Fix the client to always derive and pass the current user's identifier instead of issuing unscoped GETs.

Example fix

# before
requests.get(f"{BASE}/memories", headers=headers)  # 403 for member user

# after
requests.get(f"{BASE}/memories", params={"user_id": "alice"}, headers=headers)
Defensive patterns

Strategy: validation

Validate before calling

def list_memories(base: str, headers: dict, user_id: str | None) -> dict:
    params = {"user_id": user_id} if user_id else None
    if params is None:
        assert headers.get("Authorization") and is_admin(headers), \
            "Unscoped GET /memories requires admin credentials"
    return requests.get(f"{base}/memories", params=params, headers=headers).json()

Type guard

def is_admin(headers: dict) -> bool:
    # decode own JWT payload (middle segment) and inspect role claim
    import base64, json
    tok = headers.get("Authorization", "").removeprefix("Bearer ")
    if not tok:
        return False
    payload = tok.split(".")[1]
    claims = json.loads(base64.urlsafe_b64decode(payload + "=" * (-len(payload) % 4)))
    return claims.get("role") == "admin"

Try / catch

if resp.status_code == 403 and "Admin role required" in resp.text:
    raise PermissionError("Scope the request (user_id/agent_id/run_id) or use admin credentials")

Prevention

When it happens

Trigger: A member-role user or their personal API key calling GET /memories with no query params; a client that 'lists everything' on startup by omitting filters; admin-key auth not actually matching ADMIN_API_KEY so the caller fell into the API-key user path.

Common situations: Dashboard-style clients enumerating all memories for a demo; multi-user deployments where non-admin users share one memory store; scripts written under AUTH_DISABLED that later run against an authenticated server.

Related errors


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