Unable to add components to content library

Hi all

We are experiencing an issue trying to add new components to a content library. Basically when you save a new component it is not reflected in the library. Bellow is a video where you can see the full process.

We are working in Teak (release/teak.3), under tutor version v20.0.5

Many thanks in advance
Regards

I think this was resolved in the Ulmo release but tagging @dave to verify

I can’t see the error message because it’s unfortunately being sent as HTML, and the error is much later on in the document than what’s shown in the video. However, based on the fact that all the /multi-search requests are failing as well, it’s likely that Meilisearch is not configured correctly.

Mmm yes, maybe we shall go into it.

Currently we use the containerized meilisearch provided by tutor, but MySQL, MongoDB, Redis and Clickhouse are being ran natively in a different machine .

@braden Would you recommend separate Meilisearch to a native service aswell?

Thank you

Regards

I think the containerized Meilisearch provided by Tutor is totally sufficient for 95% of use cases! I would just stick with that unless you’re encountering performance problems.

My Meilisearch configuration is

image

Following the tutor documentation on Meilisearch it seems ok, as MEILISEARCH_API_KEY equals to MEILISEARCH_MASTER_KEY :man_shrugging:

Also I’ve found this error in CMS logs (tutor local logs cms), it dispatches when trying to create a new library component:

cms-1  | 2026-04-14 13:50:36,352 ERROR 13 [root] [user None] [ip None] signals.py:22 - Uncaught exception from None
cms-1  | Traceback (most recent call last):
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
cms-1  |     response = get_response(request)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
cms-1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
cms-1  |     return view_func(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
cms-1  |     return self.dispatch(request, *args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 46, in _wrapper
cms-1  |     return bound_method(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
cms-1  |     response = self.handle_exception(exc)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
cms-1  |     self.raise_uncaught_exception(exc)
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
cms-1  |     raise exc
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
cms-1  |     response = handler(request, *args, **kwargs)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/rest_api/utils.py", line 24, in wrapped_fn
cms-1  |     return fn(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/rest_api/blocks.py", line 96, in post
cms-1  |     result = api.create_library_block(library_key, user_id=request.user.id, **serializer.validated_data)
cms-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/api/blocks.py", line 309, in create_library_block
cms-1  |     _create_component_for_block(content_library, usage_key, user_id, can_stand_alone)
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/api/blocks.py", line 891, in _create_component_for_block
cms-1  |     component_type = authoring_api.get_or_create_component_type(
cms-1  |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/openedx_learning/apps/authoring/components/api.py", line 69, in get_or_create_component_type
cms-1  |     component_type, _created = ComponentType.objects.get_or_create(
cms-1  |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
cms-1  |     return getattr(self.get_queryset(), name)(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/query.py", line 916, in get_or_create
cms-1  |     return self.get(**kwargs), False
cms-1  |            ^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/query.py", line 640, in get
cms-1  |     raise self.model.MultipleObjectsReturned(
cms-1  | openedx_learning.apps.authoring.components.models.ComponentType.MultipleObjectsReturned: get() returned more than one ComponentType -- it returned 3!
cms-1  | 2026-04-14 13:50:36,371 ERROR 13 [django.request] [user 7268] [ip 150.244.22.149] log.py:241 - Internal Server Error: /api/libraries/v2/lib:UAMx:CSTEST/blocks/
cms-1  | Traceback (most recent call last):
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
cms-1  |     response = get_response(request)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
cms-1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
cms-1  |     return view_func(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
cms-1  |     return self.dispatch(request, *args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 46, in _wrapper
cms-1  |     return bound_method(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
cms-1  |     response = self.handle_exception(exc)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
cms-1  |     self.raise_uncaught_exception(exc)
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
cms-1  |     raise exc
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
cms-1  |     response = handler(request, *args, **kwargs)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/rest_api/utils.py", line 24, in wrapped_fn
cms-1  |     return fn(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/rest_api/blocks.py", line 96, in post
cms-1  |     result = api.create_library_block(library_key, user_id=request.user.id, **serializer.validated_data)
cms-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/api/blocks.py", line 309, in create_library_block
cms-1  |     _create_component_for_block(content_library, usage_key, user_id, can_stand_alone)
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/api/blocks.py", line 891, in _create_component_for_block
cms-1  |     component_type = authoring_api.get_or_create_component_type(
cms-1  |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/openedx_learning/apps/authoring/components/api.py", line 69, in get_or_create_component_type
cms-1  |     component_type, _created = ComponentType.objects.get_or_create(
cms-1  |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
cms-1  |     return getattr(self.get_queryset(), name)(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/query.py", line 916, in get_or_create
cms-1  |     return self.get(**kwargs), False
cms-1  |            ^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/query.py", line 640, in get
cms-1  |     raise self.model.MultipleObjectsReturned(
cms-1  | openedx_learning.apps.authoring.components.models.ComponentType.MultipleObjectsReturned: get() returned more than one ComponentType -- it returned 3!
cms-1  | [pid: 13|app: 0|req: 241/1097] 172.22.0.3 () {66 vars in 4225 bytes} [Tue Apr 14 13:50:36 2026] POST /api/libraries/v2/lib:UAMx:CSTEST/blocks/ => generated 8913 bytes in 198 msecs (HTTP/1.1 500) 10 headers in 619 bytes (1 switches on core 0)

Also, I’ve found this post where you provide a couple of solutions to a similar problem. Maybe there’s a misconfiguration there because as you say here going to https://uamxstudio-*****/api/content_search/v2/studio/ I do not received the espected JSON but a 500 server error

Thanks in advance for any help

Kind regards!

OK, you have two different issues going on:

  1. In get_or_create_component_type(): ComponentType.MultipleObjectsReturned: get() returned more than one ComponentType -- it returned 3!

    • @dave any ideas on how this should even be possible? The database constraint must not be applied correctly?!
  2. Meilisearch API error: API key not found. Yeah, please try the debugging tips in that other thread.

Also, if your instance is on the public internet, you’ll want to change your Meilisearch API keys since they’re posted in this thread. You can do that by removing any MEILISEARCH releated entries from tutor’s config file, running tutor config save and re-running tutor dev launch -I.

Yeah, the constraint wasn’t properly specified for a long while because it was defined outside the Meta of the model and didn’t make it into a proper migration. If it’s in this state, I think it would require manual database modifications to remove the redundant entries in oel_componenttype, keeping in mind that there may be entries in oel_component that have foreign keys that might need to get switched over to the correct type first. And ideally adding a new unique constraint to oel_componenttype’s (namespace, name).

Oh right. I think I recently fixed that constraint actually. But I didn’t realize people might have invalid data. Do you think I should update that migration to delete duplicates?

Sure. I guess we should just consolidate on the earliest ComponentType entry in any set of duplicates and adjust any Components that were pointing to the later duplicates?

Makes sense. Created Clean up Invalid ComponentTypes during migration · Issue #548 · openedx/openedx-core · GitHub

Hi @braden , sorry for the late response, I was required for another project while trying to solve and debug this issue.

Thanks for the tips and advices, I finally managed to fix Meilisearch URL configuration and access it normally. After that, when I tried to create a new library component I received the error on trying to search by publish_status described here. I think this is expected…

So I ran tutor local exec cms ./manage.py cms reindex_studio --experimental but the command stopped showing up the following error:

Thanks in advance for the support
Kind regards

@Yago just to chime in here, would you mind posting traces in a code block rather than a screenshot? Code blocks are searchable for other people coming to the forums looking to find similar issues, and screenshots are not searchable.

You can generate a codeblock by clicking the button here:

And then pasting the output in between the triple backticks.

Hi Sarina, thanks, I didn’t realized about that point. There it is:

281/536. Now indexing course Fundamentos de programaciĂłn (course-v1:UAMx+FundProg+22-23)
2026-04-27 08:47:05,798 WARNING 3926 [xmodule.modulestore.split_mongo.mongo_connection] [user None] [ip None] mongo_connection.py:352 - doc was None when attempting to retrieve structure for item with key 64b113e03311ff492f38b365
Traceback (most recent call last):
  File "/openedx/edx-platform/./manage.py", line 99, in <module>
    execute_from_command_line([sys.argv[0]] + django_args)
  File "/openedx/venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/openedx/venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/openedx/venv/lib/python3.11/site-packages/django/core/management/base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/openedx/venv/lib/python3.11/site-packages/django/core/management/base.py", line 458, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/edx-platform/openedx/core/djangoapps/content/search/management/commands/reindex_studio.py", line 47, in handle
    api.rebuild_index(self.stdout.write)
  File "/openedx/edx-platform/openedx/core/djangoapps/content/search/api.py", line 584, in rebuild_index
    course_docs = index_course(course)
                  ^^^^^^^^^^^^^^^^^^^^
  File "/openedx/edx-platform/openedx/core/djangoapps/content/search/api.py", line 568, in index_course
    _recurse_children(course, add_with_children)
  File "/openedx/edx-platform/openedx/core/djangoapps/content/search/api.py", line 277, in _recurse_children
    if block.has_children:
       ^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'has_children'
Error: Command failed with status 1: docker compose -f /home/tutor/manifests/env/local/docker-compose.yml -f /home/tutor/manifests/env/local/docker-compose.prod.yml --project-name tutor_local exec cms ./manage.py cms reindex_studio --experimental

@Yago I suspect it’s because this course ^ has been deleted, but there is still a reference to it in the CourseOverview table.

You can verify this by (A) checking if the course still exists or not, and (B) checking if there’s a CourseOverview entry for it (e.g. in the Django admin at /admin/course_overviews/courseoverview/)

I have a fix prepared here, please let me know if you can test it: fix: make studio reindex more robust, provide better logging [FC-0117] by bradenmacdonald · Pull Request #38498 · openedx/openedx-platform · GitHub

Hi @braden , sorry for the late response, there were some issues in other projects that requiered my whole attention.

And thanks, that PR fixes the issue creating library components, and all the components I created before appeared in my dashboard :clap:

Well there’s only one issue remaining. I still have troubles creating text components, as described above, the platforms throws this error:

2026-05-18T13:22:20.972038+00:00", "event_type": "/api/libraries/v2/lib:YAGO:YAG_001/blocks/", "event_source": "server", "page": null}
cms-1  | 2026-05-18 13:22:21,016 ERROR 13 [root] [user None] [ip None] signals.py:22 - Uncaught exception from None
cms-1  | Traceback (most recent call last):
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
cms-1  |     response = get_response(request)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
cms-1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
cms-1  |     return view_func(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
cms-1  |     return self.dispatch(request, *args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 46, in _wrapper
cms-1  |     return bound_method(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
cms-1  |     response = self.handle_exception(exc)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
cms-1  |     self.raise_uncaught_exception(exc)
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
cms-1  |     raise exc
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
cms-1  |     response = handler(request, *args, **kwargs)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/rest_api/utils.py", line 24, in wrapped_fn
cms-1  |     return fn(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/rest_api/blocks.py", line 96, in post
cms-1  |     result = api.create_library_block(library_key, user_id=request.user.id, **serializer.validated_data)
cms-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/api/blocks.py", line 309, in create_library_block
cms-1  |     _create_component_for_block(content_library, usage_key, user_id, can_stand_alone)
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/api/blocks.py", line 891, in _create_component_for_block
cms-1  |     component_type = authoring_api.get_or_create_component_type(
cms-1  |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/openedx_learning/apps/authoring/components/api.py", line 69, in get_or_create_component_type
cms-1  |     component_type, _created = ComponentType.objects.get_or_create(
cms-1  |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
cms-1  |     return getattr(self.get_queryset(), name)(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/query.py", line 916, in get_or_create
cms-1  |     return self.get(**kwargs), False
cms-1  |            ^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/query.py", line 640, in get
cms-1  |     raise self.model.MultipleObjectsReturned(
cms-1  | openedx_learning.apps.authoring.components.models.ComponentType.MultipleObjectsReturned: get() returned more than one ComponentType -- it returned 3!
cms-1  | 2026-05-18 13:22:21,031 ERROR 13 [django.request] [user 7268] [ip 150.244.22.149] log.py:241 - Internal Server Error: /api/libraries/v2/lib:YAGO:YAG_001/blocks/
cms-1  | Traceback (most recent call last):
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
cms-1  |     response = get_response(request)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
cms-1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
cms-1  |     return view_func(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
cms-1  |     return self.dispatch(request, *args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 46, in _wrapper
cms-1  |     return bound_method(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
cms-1  |     response = self.handle_exception(exc)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
cms-1  |     self.raise_uncaught_exception(exc)
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
cms-1  |     raise exc
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
cms-1  |     response = handler(request, *args, **kwargs)
cms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/rest_api/utils.py", line 24, in wrapped_fn
cms-1  |     return fn(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/rest_api/blocks.py", line 96, in post
cms-1  |     result = api.create_library_block(library_key, user_id=request.user.id, **serializer.validated_data)
cms-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/api/blocks.py", line 309, in create_library_block
cms-1  |     _create_component_for_block(content_library, usage_key, user_id, can_stand_alone)
cms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/content_libraries/api/blocks.py", line 891, in _create_component_for_block
cms-1  |     component_type = authoring_api.get_or_create_component_type(
cms-1  |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/openedx_learning/apps/authoring/components/api.py", line 69, in get_or_create_component_type
cms-1  |     component_type, _created = ComponentType.objects.get_or_create(
cms-1  |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
cms-1  |     return getattr(self.get_queryset(), name)(*args, **kwargs)
cms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/query.py", line 916, in get_or_create
cms-1  |     return self.get(**kwargs), False
cms-1  |            ^^^^^^^^^^^^^^^^^^
cms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/db/models/query.py", line 640, in get
cms-1  |     raise self.model.MultipleObjectsReturned(
cms-1  | openedx_learning.apps.authoring.components.models.ComponentType.MultipleObjectsReturned: get() returned more than one ComponentType -- it returned 3!

It happens only in Text components, every other Content works well. Should I create a new post to focus on this issue or is OK to keep it here?

Thanks again!

Regards

That error will be fixed in Verawood and newer with the fix from this PR: fix: handle duplicates when applying CompontentType constraint by bradenmacdonald · Pull Request #572 · openedx/openedx-core · GitHub

Until then, to fix it manually, you’ll need to get access to the CMS Django shell (e.g. something like tutor local exec cms ./manage.py shell) and then paste in this script to delete the duplicates:

from django.db.models import Count, Min

duplicate_groups = ComponentType.objects.values("namespace", "name").annotate(num=Count("id"), keep_id=Min("id")).filter(num__gt=1)

for group in duplicate_groups:
    keep_id = group["keep_id"]
    duplicate_ids = list(
        ComponentType.objects.filter(namespace=group["namespace"], name=group["name"])
        .exclude(id=keep_id)
        .values_list("id", flat=True)
    )
    Component.objects.filter(component_type_id__in=duplicate_ids).update(component_type_id=keep_id)
    ComponentType.objects.filter(id__in=duplicate_ids).delete()

Thanks @braden , this fixes the issue! Just one note, I have had to add some dependencies to the script, so it was like the following:

from django.apps import apps
from django.db import transaction
from django.db.models import Count, Min

ComponentType = apps.get_model("oel_components", "ComponentType")
Component = apps.get_model("oel_components", "Component")

duplicate_groups = ComponentType.objects.values("namespace", "name").annotate(num=Count("id"), keep_id=Min("id")).filter(num__gt=1)

for group in duplicate_groups:
     keep_id = group["keep_id"]
     duplicate_ids = list(
         ComponentType.objects.filter(namespace=group["namespace"], name=group["name"])
         .exclude(id=keep_id)
         .values_list("id", flat=True)
     )
     Component.objects.filter(component_type_id__in=duplicate_ids).update(component_type_id=keep_id)
     ComponentType.objects.filter(id__in=duplicate_ids).delete()