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

  1. Complete the media upload first and pass media_comment_id (and optional media_comment_type) when creating the submission
  2. Verify the media object exists (MediaObject/MediaComment for the id) before submitting; retry the upload if it failed
  3. 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

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


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 now

View on GitHub (pinned to 1c9f0bb801)