{"record":{"id":"b43438b6486767eb","repo":"mem0ai/mem0","slug":"at-least-one-entity-id-is-required-for-deleteentit","errorCode":null,"errorMessage":"At least one entity ID is required for deleteEntities.","messagePattern":"At least one entity ID is required for deleteEntities\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/node/src/backend/platform.ts","lineNumber":351,"sourceCode":"\t\t\t\t\"DELETE\",\n\t\t\t\t`/v1/memories/${encodePathSegment(memoryId)}/`,\n\t\t\t\t{ params },\n\t\t\t)) as Record<string, unknown>;\n\t\t}\n\t\tthrow new Error(\"Either memoryId or --all is required\");\n\t}\n\n\tasync deleteEntities(opts: EntityIds): Promise<Record<string, unknown>> {\n\t\t// v2 endpoint: DELETE /v2/entities/{entity_type}/{entity_id}/\n\t\tconst typeMap: [string, string | undefined][] = [\n\t\t\t[\"user\", opts.userId],\n\t\t\t[\"agent\", opts.agentId],\n\t\t\t[\"app\", opts.appId],\n\t\t\t[\"run\", opts.runId],\n\t\t];\n\t\tconst entities = typeMap.filter(([, v]) => v) as [string, string][];\n\t\tif (entities.length === 0) {\n\t\t\tthrow new Error(\"At least one entity ID is required for deleteEntities.\");\n\t\t}\n\t\t// Delete each provided entity via the v2 path-based endpoint. Key each\n\t\t// response by entity type so a multi-entity delete (e.g. --user-id and\n\t\t// --agent-id together) doesn't discard everything but the last result.\n\t\tconst results: Record<string, unknown> = {};\n\t\tfor (const [entityType, entityId] of entities) {\n\t\t\tresults[entityType] = (await this._request(\n\t\t\t\t\"DELETE\",\n\t\t\t\t`/v2/entities/${encodePathSegment(entityType)}/${encodePathSegment(entityId)}/`,\n\t\t\t\t{ params: { source: \"CLI\" } },\n\t\t\t)) as Record<string, unknown>;\n\t\t}\n\t\treturn results;\n\t}\n\n\tasync ping(): Promise<Record<string, unknown>> {\n\t\treturn (await this._request(\"GET\", \"/v1/ping/\")) as Record<string, unknown>;\n\t}","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/cli/node/src/backend/platform.ts#L333-L369","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use credentials of a user with role='admin' (by default, the account created via /setup / first POST /auth/register).","If the intended operator should be admin, promote them directly in the DB: UPDATE users SET role='admin' WHERE email='...'.","Scope client operations to non-admin endpoints when a member account is intentional (e.g. pass user_id filters instead of listing all memories)."],"exampleFix":"# before\n# token belongs to user with role='member'\nrequests.post(f\"{BASE}/reset\", headers={\"Authorization\": f\"Bearer {member_token}\"})  # 403\n\n# after\nadmin_tok = login(admin_email, admin_password)\nrequests.post(f\"{BASE}/reset\", headers={\"Authorization\": f\"Bearer {admin_tok['access_token']}\"})","handlingStrategy":"validation","validationCode":"token_data = decode_jwt(access_token)  # client-side decode of payload\nif token_data.get(\"role\") != \"admin\":\n    raise PermissionError(\"This operation requires an admin account; current token role: \" + str(token_data.get(\"role\")))","typeGuard":"def is_admin_token(claims: dict) -> bool:\n    return claims.get(\"role\") == \"admin\"","tryCatchPattern":"if resp.status_code == 403 and \"Admin role required\" in resp.text:\n    raise PermissionError(\"Non-admin credentials used on admin endpoint\")  # never retry with same token","preventionTips":["Separate admin and member credentials in configuration by intent.","Expose destructive operations only through admin-configured clients.","In tests, create one admin fixture and reuse it for admin endpoints."],"tags":["auth","http-403","authorization","rbac","rest-server"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}