{"record":{"id":"2a3ef6aca7c8140b","repo":"instructure/canvas-lms","slug":"can-t-create-media-submission-without-media-object","errorCode":null,"errorMessage":"Can't create media submission without media object","messagePattern":"Can't create media submission without media object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/models/submission.rb","lineNumber":1737,"sourceCode":"    if (workflow_state_changed? && graded?) || late_policy_status_changed?\n      self.graded_at = Time.zone.now\n    end\n    self.media_comment_id = nil if media_comment_id && media_comment_id.strip.empty?\n    if media_comment_id && (media_comment_id_changed? || !media_object_id)\n      mo = MediaObject.by_media_id(media_comment_id).first\n      self.media_object_id = mo && mo.id\n      if mo && submission_type == \"media_recording\" && mo.attachment_id\n        self.attachment_id = mo.attachment_id\n      end\n    end\n    self.media_comment_type = nil unless media_comment_id\n    if self.submitted_at\n      self.attempt ||= 0\n      self.attempt += 1 if submitted_at_changed?\n      self.attempt = 1 if self.attempt < 1\n    end\n    if submission_type == \"media_recording\" && !media_comment_id\n      raise \"Can't create media submission without media object\"\n    end\n\n    if submission_type == \"online_quiz\"\n      self.quiz_submission ||= Quizzes::QuizSubmission.where(submission_id: self).first\n      self.quiz_submission ||= Quizzes::QuizSubmission.where(user_id:, quiz_id: assignment.quiz).first if assignment\n    end\n    @just_submitted = (submitted? || pending_review?) && submission_type && (new_record? || workflow_state_changed? || attempt_changed?)\n    if score_changed? || grade_changed?\n      self.grade = if assignment\n                     assignment.score_to_grade(score, grade)\n                   else\n                     score.to_s\n                   end\n    end\n\n    self.grade = nil unless score\n    # I think the idea of having unpublished scores is unnecessarily confusing.\n    # It may be that we want to have that functionality later on, but for now","sourceCodeStart":1719,"sourceCodeEnd":1755,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/submission.rb#L1719-L1755","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nsubmission = @assignment.submit_homework(\n  @user, submission_type: 'media_recording'\n)\n// after\nsubmission = @assignment.submit_homework(\n  @user,\n  submission_type: 'media_recording',\n  media_comment_id: media_object.media_id,\n  media_comment_type: 'video'\n)","handlingStrategy":"validation","validationCode":"raise 'media required' if params[:submission_type] == 'media_recording' && params[:media_comment_id].blank?","typeGuard":"params[:media_comment_id].present?","tryCatchPattern":"begin\n  assignment.submit_homework(user, params)\nrescue RuntimeError => e\n  retry_with_media_upload if e.message.include?('media submission')\nend","preventionTips":["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"],"tags":["submission","media","validation"],"backgroundTag":"empty-required-field","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}