mem0ai/mem0 · error · Error

At least one entity ID is required for deleteEntities.

Error message

At least one entity ID is required for deleteEntities.

What it means

The final check in require_admin: a real, authenticated User was resolved (valid JWT or personal API key) but that user's role is not 'admin'. Admin-only operations (reset all memories, delete all memories, etc.) are restricted to the admin role even for successfully authenticated users. HTTP 403.

Source

Thrown at cli/node/src/backend/platform.ts:351

				"DELETE",
				`/v1/memories/${encodePathSegment(memoryId)}/`,
				{ params },
			)) as Record<string, unknown>;
		}
		throw new Error("Either memoryId or --all is required");
	}

	async deleteEntities(opts: EntityIds): Promise<Record<string, unknown>> {
		// v2 endpoint: DELETE /v2/entities/{entity_type}/{entity_id}/
		const typeMap: [string, string | undefined][] = [
			["user", opts.userId],
			["agent", opts.agentId],
			["app", opts.appId],
			["run", opts.runId],
		];
		const entities = typeMap.filter(([, v]) => v) as [string, string][];
		if (entities.length === 0) {
			throw new Error("At least one entity ID is required for deleteEntities.");
		}
		// Delete each provided entity via the v2 path-based endpoint. Key each
		// response by entity type so a multi-entity delete (e.g. --user-id and
		// --agent-id together) doesn't discard everything but the last result.
		const results: Record<string, unknown> = {};
		for (const [entityType, entityId] of entities) {
			results[entityType] = (await this._request(
				"DELETE",
				`/v2/entities/${encodePathSegment(entityType)}/${encodePathSegment(entityId)}/`,
				{ params: { source: "CLI" } },
			)) as Record<string, unknown>;
		}
		return results;
	}

	async ping(): Promise<Record<string, unknown>> {
		return (await this._request("GET", "/v1/ping/")) as Record<string, unknown>;
	}

View on GitHub (pinned to 001c235229)

Solutions

  1. Use credentials of a user with role='admin' (by default, the account created via /setup / first POST /auth/register).
  2. If the intended operator should be admin, promote them directly in the DB: UPDATE users SET role='admin' WHERE email='...'.
  3. Scope client operations to non-admin endpoints when a member account is intentional (e.g. pass user_id filters instead of listing all memories).

Example fix

# before
# token belongs to user with role='member'
requests.post(f"{BASE}/reset", headers={"Authorization": f"Bearer {member_token}"})  # 403

# after
admin_tok = login(admin_email, admin_password)
requests.post(f"{BASE}/reset", headers={"Authorization": f"Bearer {admin_tok['access_token']}"})
Defensive patterns

Strategy: validation

Validate before calling

token_data = decode_jwt(access_token)  # client-side decode of payload
if token_data.get("role") != "admin":
    raise PermissionError("This operation requires an admin account; current token role: " + str(token_data.get("role")))

Type guard

def is_admin_token(claims: dict) -> bool:
    return claims.get("role") == "admin"

Try / catch

if resp.status_code == 403 and "Admin role required" in resp.text:
    raise PermissionError("Non-admin credentials used on admin endpoint")  # never retry with same token

Prevention

When it happens

Trigger: Logging in as a non-admin member user and calling DELETE /memories, POST /reset, or any route with Depends(require_admin); creating a second user account and reusing its token for admin operations.

Common situations: Multi-user deployments where only the first registered account is admin; a client hardcodes one token for all operations after additional non-admin users were added; tests that register a fresh user per run (each new user after the first is non-admin) and then call admin endpoints.

Related errors


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