From 8f178750188d9dc6ea610f9625e33e44cc2e9f19 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 18 May 2026 18:49:02 +0200 Subject: [PATCH] fix: handle missing forum account gracefully during user retirement Two cases now handled in the forum-v2 path of User.retire(): - ForumV2RequestError: user has no forum account (never posted), no-op. - IntegrityError: blank email already used by a previously retired user; the forum package sets email="" which violates the unique constraint when another retired user already has that value. Log and continue. Co-Authored-By: Claude Sonnet 4.6 --- .../django_comment_common/comment_client/user.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/user.py b/openedx/core/djangoapps/django_comment_common/comment_client/user.py index eaac6b408659..52a8a3172fea 100644 --- a/openedx/core/djangoapps/django_comment_common/comment_client/user.py +++ b/openedx/core/djangoapps/django_comment_common/comment_client/user.py @@ -1,11 +1,17 @@ # pylint: disable=missing-docstring,protected-access """ User model wrapper for comment service""" +import logging + +from django.db import IntegrityError + from . import models, settings, utils from forum import api as forum_api from forum.utils import ForumV2RequestError, str_to_bool from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled +log = logging.getLogger(__name__) + class User(models.Model): @@ -286,7 +292,14 @@ def _retrieve(self, *args, **kwargs): def retire(self, retired_username): course_key = utils.get_course_key(self.attributes.get("course_id")) if is_forum_v2_enabled(course_key): - forum_api.retire_user(user_id=self.id, retired_username=retired_username, course_id=str(course_key)) + try: + forum_api.retire_user(user_id=self.id, retired_username=retired_username, course_id=str(course_key)) + except ForumV2RequestError: + # User has no forum account (never posted), so there is nothing to retire. + pass + except IntegrityError: + # Blank email already exists from a previously retired user. Log and continue. + log.warning("Forum retirement for user %s skipped due to duplicate email constraint.", self.id) else: url = _url_for_retire(self.id) params = {'retired_username': retired_username}