instructure/canvas-lms · error
Can't create media submission without media object
Error message
Can't create media submission without media object
What it means
Submission#infer_values enforces that a media_recording submission carries a media comment id referencing the uploaded media object. This guard fires when submission_type is 'media_recording' but media_comment_id is blank, meaning there is no actual media artifact to grade. It is a data-integrity check during submission value inference (before save).
Solutions
- Complete the media upload first and pass media_comment_id (and optional media_comment_type) when creating the submission
- Verify the media object exists (MediaObject/MediaComment for the id) before submitting; retry the upload if it failed
- If the submission already exists with type media_recording but no id, either re-upload the media or change the submission_type
Example fix
// before submission = @assignment.submit_homework( @user, submission_type: 'media_recording' ) // after submission = @assignment.submit_homework( @user, submission_type: 'media_recording', media_comment_id: media_object.media_id, media_comment_type: 'video' )
Defensive patterns
Strategy: validation
Validate before calling
raise 'media required' if params[:submission_type] == 'media_recording' && params[:media_comment_id].blank?
Type guard
params[:media_comment_id].present?
Try / catch
begin
assignment.submit_homework(user, params)
rescue RuntimeError => e
retry_with_media_upload if e.message.include?('media submission')
end Prevention
- Finish the media upload before creating the submission
- Pass media_comment_id and media_comment_type together
- Retry failed media uploads client-side before submitting
When it happens
Trigger: Creating/updating a submission with submission_type: 'media_recording' and no media_comment_id; the client uploads media through kaltura/canvas media API but the media_comment_id is not passed when the submission is created; media upload succeeded asynchronously but the submission was saved before the id was attached.
Common situations: Mobile clients or LTI tools that submit media out-of-band and forget to link the media id; API callers submitting media_recording via the create-submission endpoint without media_comment_id; flaky media uploads that failed silently leaving the id nil.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- cannot change column: captions - locked by Master Course
- A course did not pass validation
- A # user did not pass validation (user: # , # : # , error…
- A maximum of 50 assessees can be provided at once
- A maximum of 50 assessors can be provided at once
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/2a3ef6aca7c8140b.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/submission.rb:1737
if (workflow_state_changed? && graded?) || late_policy_status_changed?
self.graded_at = Time.zone.now
end
self.media_comment_id = nil if media_comment_id && media_comment_id.strip.empty?
if media_comment_id && (media_comment_id_changed? || !media_object_id)
mo = MediaObject.by_media_id(media_comment_id).first
self.media_object_id = mo && mo.id
if mo && submission_type == "media_recording" && mo.attachment_id
self.attachment_id = mo.attachment_id
end
end
self.media_comment_type = nil unless media_comment_id
if self.submitted_at
self.attempt ||= 0
self.attempt += 1 if submitted_at_changed?
self.attempt = 1 if self.attempt < 1
end
if submission_type == "media_recording" && !media_comment_id
raise "Can't create media submission without media object"
end
if submission_type == "online_quiz"
self.quiz_submission ||= Quizzes::QuizSubmission.where(submission_id: self).first
self.quiz_submission ||= Quizzes::QuizSubmission.where(user_id:, quiz_id: assignment.quiz).first if assignment
end
@just_submitted = (submitted? || pending_review?) && submission_type && (new_record? || workflow_state_changed? || attempt_changed?)
if score_changed? || grade_changed?
self.grade = if assignment
assignment.score_to_grade(score, grade)
else
score.to_s
end
end
self.grade = nil unless score
# I think the idea of having unpublished scores is unnecessarily confusing.
# It may be that we want to have that functionality later on, but for nowView on GitHub (pinned to 1c9f0bb801)