Fix exercise extra_fields migration for non-m_of_n mastery models#5714
Merged
rtibbles merged 6 commits intolearningequality:hotfixesfrom Feb 20, 2026
Merged
Fix exercise extra_fields migration for non-m_of_n mastery models#5714rtibbles merged 6 commits intolearningequality:hotfixesfrom
rtibbles merged 6 commits intolearningequality:hotfixesfrom
Conversation
Old-style exercise extra_fields were being migrated with non-null m/n values for non-m_of_n mastery models (e.g. do_all, num_correct_in_a_row). The mastery criteria JSON schema requires m and n to be null for these models, causing frontend AJV validation to fail and exercises to appear incomplete. - Fix migrate_extra_fields to set m/n to null for non-m_of_n models - Add management command fix_exercise_extra_fields to repair existing data in production Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The ricecooker import path (create_node) was writing old-style extra_fields directly to the DB without running migration. This ensures incoming exercise data is migrated to the new-style options.completion_criteria format before being persisted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rtibbles
commented
Feb 20, 2026
| not extra_fields.get("options", {}).get("completion_criteria", {}) | ||
| and mastery_model is not None | ||
| ): | ||
| if mastery_model != exercises.M_OF_N: |
Member
Author
There was a problem hiding this comment.
This is the core of the fix, really - m and n should be None if we don't have an exercises.M_OF_N mastery model.
bjester
reviewed
Feb 20, 2026
contentcuration/contentcuration/management/commands/fix_exercise_extra_fields.py
Show resolved
Hide resolved
contentcuration/contentcuration/management/commands/fix_exercise_extra_fields.py
Show resolved
Hide resolved
contentcuration/contentcuration/management/commands/fix_exercise_extra_fields.py
Outdated
Show resolved
Hide resolved
contentcuration/contentcuration/management/commands/fix_exercise_extra_fields.py
Outdated
Show resolved
Hide resolved
Member
Author
|
Updated! |
bjester
reviewed
Feb 20, 2026
contentcuration/contentcuration/management/commands/fix_exercise_extra_fields.py
Show resolved
Hide resolved
bjester
approved these changes
Feb 20, 2026
Member
bjester
left a comment
There was a problem hiding this comment.
LGTM! Tests have good coverage over critical logic. Dry run logic and command logging makes sense
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
migrate_extra_fieldswas carrying over non-nullm/nvalues for non-m_of_n mastery models (e.g.do_all,num_correct_in_a_row). The mastery criteria JSON schema requiresmandnto benullfor these models, causing frontend AJV validation to fail and exercises to appear incomplete — even though backendmark_completepassed them (it skips schema validation for old-style data).Fixing just the m/n nulling in
migrate_extra_fieldswould have been sufficient to resolve the immediate bug. However, to avoid having to worry about old-style exercise data ever again, this PR also:create_node) to runmigrate_extra_fieldson incoming exercise data before writing to DBfix_exercise_extra_fieldsto repair existing data in production — both already-migrated exercises with invalid m/n and any remaining old-style exercises that haven't been migrated yetVerification: all new and existing tests pass (
test_contentnodes.py,test_views_internal.py).References
Fixes #5667
Reviewer guidance
utils/nodes.py:528-530— the core fix: 3 lines that null out m/n for non-m_of_n models. This runs on every exercise API read/write viaconsolidate_extra_fieldsandExtraFieldsSerializer.update, so correctness here is critical. Onlym_of_nshould preserve m/n values; all other mastery models should have them set to null.views/internal.py:839-842— addingmigrate_extra_fieldsto the ricecooker import path. This runs before the existingcompletion_criteria.validate()block, so newly-migrated data gets validated too. Test coverage confirms new-style extra_fields pass through unchanged.iterator()with Python-side filtering to avoid expensive nested JSON queries. Individualsave(update_fields=...)per affected node. Safe for large datasets but will be slow on production (millions of exercises). Run with--dry-runfirst to verify counts.