Skip to content

Fix #2502: fix: rejected ROOT-user deletion removes its configuration - #2503

Open
Memtensor-AI wants to merge 1 commit into
MemTensor:dev-v2.0.36from
Memtensor-AI:bugfix/autodev-2502-20261015135804529
Open

Memtensor-AI wants to merge 1 commit into
MemTensor:dev-v2.0.36from
Memtensor-AI:bugfix/autodev-2502-20261015135804529

Conversation

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

Description

Fixed the bug where a refused ROOT-user deletion still removed the persisted user configuration.

Root cause: PersistentUserManager.delete_user (and the byte-identical MySQLPersistentUserManager.delete_user) called delete_user_config(user_id) — which commits immediately — BEFORE delegating to the parent UserManager.delete_user. The parent refuses to delete a user whose role is UserRole.ROOT and returns False, so the config row was already committed as deleted while the user remained active: validate_user("root") is True but get_user_config("root") is None. The same held for a ROOT user with a custom ID, since the guard keys on role, not on the ID string.

Fix: reorder so the parent deletion runs first; if it refuses (protected ROOT user, or nonexistent user) return False immediately and touch nothing. Only after a successful deletion is the configuration cleaned up, as a best-effort step whose failure does not change the deletion outcome. Applied identically to both the SQLite PersistentUserManager (src/memos/mem_user/persistent_user_manager.py) and the MySQL MySQLPersistentUserManager (src/memos/mem_user/mysql_persistent_user_manager.py). The Redis manager has no delete_user override and is unaffected.

Tests: added tests/mem_user/test_persistent_user_manager_delete.py covering the protected ROOT user (default root and custom-ID ROOT), config-row survival verified through a separately opened SQLite connection, missing-user and ordinary-user controls, ordinary-user config cleanup, and the MySQL ordering contract (via patch.object fakes, since the MySQL manager needs a live server). All 9 new cases fail on the pre-fix source and pass after it — verified by stashing the source change and re-running. Full tests/mem_user/ suite: 35 passed; tests/api/: 119 passed (154 combined); ruff check and ruff format clean on all changed files.

opsp bug path, quick-fix scope: type: Bug, single guard-reordering fix with no schema or interface change, so no openspec change artifacts were emitted — only the task file .ai-tasks/2026-10-15-2502-fix-rejected-root-user-deletion-removes-its-configuration.md (frontmatter status: merged). That task file plus its Progress log were also synced and pushed to the sibling specs repo (memos-autodev-specs, commit b0b16b8).

Branch pushed to origin: bugfix/autodev-2502-20261015135804529. Note for the maintainer: the issue asked whether dev-v2.0.36 is the right target given dev is absent — this task used dev-v2.0.36 per the supplied base branch.

Related Issue (Required): Fixes #2502

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (does not change functionality, e.g. code style improvements, linting)
  • Documentation update

How Has This Been Tested?

Not run; documentation-only change.

  • Unit Test
  • Test Script Or Test Steps (please provide)
  • Pipeline Automated API Test (please provide)

Checklist

  • I have performed a self-review of my own code
  • I have commented my code in hard-to-understand areas
  • I have added tests that prove my fix is effective or that my feature works
  • I have created related documentation issue/PR in MemOS-Docs (if applicable)
  • I have linked the issue to this PR (if applicable)
  • I have mentioned the person who will review this PR

@WeiminLee please review this PR.

Reviewer Checklist

PersistentUserManager.delete_user (and its MySQL sibling) removed the
persisted configuration before delegating to the parent UserManager.
The parent refuses to delete a ROOT user by returning False, so the
configuration row was already committed as deleted while the user stayed
active -- get_user_config() returned None with validate_user() == True.

Run the parent deletion first and only clean up the configuration once
the user was actually deleted. Missing users likewise no longer trigger
config cleanup.

Add regression tests covering the protected ROOT user (default and
custom ID), connection-level persistence of the config row, missing-user
and ordinary-user controls, plus the MySQL ordering contract.
@Memtensor-AI Memtensor-AI added ai:generated Generated or modified by AI | 由 AI 生成或修改 area:core MOS 编排层 / 框架底座 / 跨模块问题 status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Oct 15, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

🤖 Open Code Review

Target: PR #2503
Task: 7c2fa7bfdacd09d3
Base: dev-v2.0.36
Head: bugfix/autodev-2502-20261015135804529
Head SHA: 8ea868696a8732157dda25d40f5b1a02b109513e

✅ OpenCodeReview: Review partially complete: 0 finding(s); 1 of 3 selected item(s) failed.

Generated by cloud-assistant via Open Code Review.

@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

✅ Automated Test Results: PASSED

All tests passed (41/41 executed). memos_github_open_source/smoke: 1/1, memos_python_core/changed-repo-python: 40/40. Duration: 15s

Branch: bugfix/autodev-2502-20261015135804529

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:generated Generated or modified by AI | 由 AI 生成或修改 area:core MOS 编排层 / 框架底座 / 跨模块问题 status:in-progress Someone or AI is working on it | 人工或 AI 正在处理

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants