Skip to content

reindex_course --all fails: Unknown tab type 'wikimedia_progress_tab' #653

Description

@Syed-Ali-Abbas-568

Summary

Running a full course reindex on the Teak instance raises a PluginError for the tab type wikimedia_progress_tab:

tutor k8s exec cms -- ./manage.py cms reindex_course --all
edx_django_utils.plugins.plugin_manager.PluginError:
No such plugin wikimedia_progress_tab for entry point openedx.course_tab

Root cause

The course data references a course tab whose plugin is no longer installed.

  • The wikimedia_progress_tab plugin was registered on the old develop (Maple) branch via the openedx.course_tab entry point.
  • It is not present on develop-teak, the branch Stage builds from. The plugin class and its wikimedia_features.progress_tab package were never carried forward.
  • Courses authored on Maple still carry a tab of type wikimedia_progress_tab in their stored tabs field. On Teak, CourseTab.from_json can't resolve the type, logs the error, and drops the tab from the in-memory list — but the stale entry remains in the modulestore.

It is a data-vs-code mismatch, not corruption.

Scope

Only one course is affected (found on Stage, running week-old production data):

course-v1:Wikimedia-Israel+WMIL_001+2024

Production may carry the tab on a different course, though this is unlikely. The diagnostic below scans by course id, so re-run it against any suspect course on prod.

Resolution

Strip the stale wikimedia_progress_tab entry from the affected course's tabs field via the modulestore API. The stock progress tab is already registered on Teak, so the course keeps a working Progress tab after the fix.

1. Open a CMS shell

tutor k8s exec cms -- ./manage.py cms shell

2. Diagnose (dry run, no writes)

Paste the block below with APPLY = False. It reads the raw stored tabs field (the deserialized course.tabs has already silently dropped the bad entry, so it must be read at the field-data layer).

exec('''
from xmodule.modulestore.django import modulestore
from opaque_keys.edx.keys import CourseKey
from django.contrib.auth import get_user_model

APPLY = False   # flip to True for the real run
TAB = "wikimedia_progress_tab"
CID = "course-v1:Wikimedia-Israel+WMIL_001+2024"

store = modulestore()
key = CourseKey.from_string(CID)
course = store.get_course(key)

raw = course._field_data.get(course, "tabs")
before = list(raw)
kept = [t for t in before if not (isinstance(t, dict) and t.get("type") == TAB)]
removed = len(before) - len(kept)

print(f"course : {CID}")
print(f"tabs   : {len(before)} -> {len(kept)}  (removing {removed})")
print("removed types:", [t.get("type") for t in before if t not in kept])
print("kept types   :", [t.get("type") for t in kept])

if APPLY and removed:
    u = get_user_model().objects.filter(is_superuser=True).order_by("id").first()
    assert u, "no superuser to attribute the edit to"
    course._field_data.set(course, "tabs", kept)
    store.update_item(course, u.id)
    print(f"SAVED. removed {removed} tab(s) as {u.username}")
elif not APPLY:
    print("DRY-RUN only. Set APPLY=True and re-run to persist.")
else:
    print("nothing to remove.")
''')

Expected dry-run output:

course : course-v1:Wikimedia-Israel+WMIL_001+2024
tabs   : 9 -> 8  (removing 1)
removed types: ['wikimedia_progress_tab']
kept types   : ['course_info', 'courseware', 'textbooks', 'discussion', 'wiki', 'progress', 'static_tab', 'dates']
DRY-RUN only. Set APPLY=True and re-run to persist.

A single from_json traceback prints when get_course() deserializes the not-yet-fixed data. It is harmless log noise, not a failure — the script runs past it.

3. Apply

Confirm the dry-run output removes only wikimedia_progress_tab, then change one line:

APPLY = True

Paste the block again. The final line should read SAVED. removed 1 tab(s) as <username>.

4. Verify

Reindex only the affected course:

tutor k8s exec cms -- ./manage.py cms reindex_course course-v1:Wikimedia-Israel+WMIL_001+2024

A clean run with no Unknown tab type line confirms the fix.

Notes

  • Writes go through store.update_item(...), not raw Mongo, so split versioning and caching stay consistent.
  • If the verification reindex still logs the error after a successful SAVED, the tab exists on both the published and draft branches and only one was fixed. A branch-aware variant is needed in that case.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions