From e8c26f83942ec5b26f676082f6dfdf634432897e Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Mon, 21 Sep 2026 17:22:21 +0200 Subject: [PATCH] fix: stop the background memory review when memory is switched off (#30309) With memories disabled instance-wide, or for a user barred from the feature, the background review still ran every interval turn: it spent a task-model call drafting memory operations and only then failed at the write, because the router's permission check rejected it. The review now checks the 'memories.enable' switch and re-checks the 'features.memories' permission the same way the context-injection path already does, so a model whose memory capability is on no longer triggers memory work that can never land. The permission lookup costs a groups query, so it runs last, after the free config and interval gates; those stay on every turn's hot path. --- backend/open_webui/utils/memory.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/utils/memory.py b/backend/open_webui/utils/memory.py index 96eb28a6e1..1308c44dd8 100644 --- a/backend/open_webui/utils/memory.py +++ b/backend/open_webui/utils/memory.py @@ -8,6 +8,7 @@ from typing import Any from fastapi import HTTPException from open_webui.models.config import Config from open_webui.models.memories import Memories +from open_webui.utils.access_control import has_permission from open_webui.utils.json_codec import JSONCodec from open_webui.utils.misc import add_or_update_system_message, get_content_from_message @@ -428,10 +429,12 @@ async def review_memory_after_turn( return config = await Config.get_many( + 'memories.enable', 'memories.background_review.enable', 'memories.review_interval_turns', + 'user.permissions', ) - if not config.get('memories.background_review.enable'): + if not config.get('memories.enable') or not config.get('memories.background_review.enable'): return try: @@ -443,6 +446,10 @@ async def review_memory_after_turn( if user_turns == 0 or user_turns % interval != 0: return + # features is client-supplied; re-check the permission the memory routes enforce. + if user.role != 'admin' and not await has_permission(user.id, 'features.memories', config.get('user.permissions')): + return + task = asyncio.create_task( _review_memory( request=request,