GET /api/courses/v1/blocks/?course_id=<key>&username=<learner>&depth=all
answers HTTP 500 with the LMS error page when the learner is enrolled in a
course whose start date has not passed. The log shows KeyError: 'self_paced'
then AttributeError: Field self_paced does not exist, raised from the
course-blocks transformers reading the course block's fields.
Every neighbouring learner endpoint handles the same state cleanly:
course_home/course_metadata returns
course_access: {has_access: false, error_code: "course_not_started"}
course_home/v1/outline and /navigation answer
403 {"detail": "Course has not started"}
courseware/sequence/<id> answers 404
- the same Blocks API call as global staff answers 200
Moving the course start into the past makes the learner's call answer 200.
Expected: answer the not-started case the way the course-home APIs do, with
a 403 carrying the access error, rather than reaching the transformers with a
course whose fields were never collected.
GET /api/courses/v1/blocks/?course_id=<key>&username=<learner>&depth=allanswers HTTP 500 with the LMS error page when the learner is enrolled in a
course whose start date has not passed. The log shows
KeyError: 'self_paced'then
AttributeError: Field self_paced does not exist, raised from thecourse-blocks transformers reading the course block's fields.
Every neighbouring learner endpoint handles the same state cleanly:
course_home/course_metadatareturnscourse_access: {has_access: false, error_code: "course_not_started"}course_home/v1/outlineand/navigationanswer403 {"detail": "Course has not started"}courseware/sequence/<id>answers 404Moving the course start into the past makes the learner's call answer 200.
Expected: answer the not-started case the way the course-home APIs do, with
a 403 carrying the access error, rather than reaching the transformers with a
course whose fields were never collected.