From a2ef5151012bb76f773e501a7116ac263d0289e7 Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Fri, 12 Dec 2025 22:17:02 +0530 Subject: [PATCH] fix: handle PluginMissingError while migrating legacy blocks to libraries v2 (#37732) Unhandled exception while migration legacy xblocks into new library stops the migration process abruptly causing following issues: * Components not being collected into Collections for successful migrations * Data being corrupted for already migrated blocks most likely due to incomplete transaction. (cherry picked from commit a3cc78a37726cc9e49497d2eed8b99b16927ef14) --- cms/djangoapps/modulestore_migrator/tasks.py | 4 +++ .../modulestore_migrator/tests/test_tasks.py | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/cms/djangoapps/modulestore_migrator/tasks.py b/cms/djangoapps/modulestore_migrator/tasks.py index ef2386c69d34..fd2fa5a4fd07 100644 --- a/cms/djangoapps/modulestore_migrator/tasks.py +++ b/cms/djangoapps/modulestore_migrator/tasks.py @@ -40,6 +40,7 @@ from user_tasks.tasks import UserTask, UserTaskStatus from xblock.core import XBlock from django.utils.translation import gettext_lazy as _ +from xblock.plugin import PluginMissingError from common.djangoapps.split_modulestore_django.models import SplitModulestoreCourseIndex from common.djangoapps.util.date_utils import strftime_localized, DEFAULT_DATE_TIME_FORMAT @@ -1142,6 +1143,9 @@ def _migrate_component( except libraries_api.IncompatibleTypesError as e: log.error(f"Error validating block for library {context.target_library_key}: {e}") return None + except PluginMissingError as e: + log.error(f"Block type not supported in {context.target_library_key}: {e}") + return None component = authoring_api.create_component( context.target_package_id, component_type=component_type, diff --git a/cms/djangoapps/modulestore_migrator/tests/test_tasks.py b/cms/djangoapps/modulestore_migrator/tests/test_tasks.py index 244d435de50a..4335d615ad2f 100644 --- a/cms/djangoapps/modulestore_migrator/tests/test_tasks.py +++ b/cms/djangoapps/modulestore_migrator/tests/test_tasks.py @@ -1748,6 +1748,34 @@ def test_bulk_migrate_invalid_source_key_type(self): f"Not a valid source context key: {invalid_key}. Source key must reference a course or a legacy library." ) + def test_migrate_component_with_fake_block_type(self): + """ + Test _migrate_component with with_fake_block_type + """ + source_key = self.course.id.make_usage_key("fake_block", "test_fake_block") + olx = '' + context = _MigrationContext( + existing_source_to_target_keys={}, + target_package_id=self.learning_package.id, + target_library_key=self.library.library_key, + source_context_key=self.course.id, + content_by_filename={}, + composition_level=CompositionLevel.Unit, + repeat_handling_strategy=RepeatHandlingStrategy.Skip, + preserve_url_slugs=True, + created_at=timezone.now(), + created_by=self.user.id, + ) + + result = _migrate_component( + context=context, + source_key=source_key, + olx=olx, + title="test" + ) + + self.assertIsNone(result) + def test_migrate_from_modulestore_nonexistent_modulestore_item(self): """ Test migration when modulestore item doesn't exist