instructure/canvas-lms · error · GraphQL::ExecutionError

not found

Error message

not found

What it means

CreateSubmissionComment#resolve raises 'not found' when MediaObject.by_media_id(input[:media_object_id]) returns empty, i.e. no MediaObject row matches the given media_id for the current context. The media_id namespace is scoped (by_media_id filters by context/user), so a valid-looking ID from elsewhere still yields an empty relation.

Solutions

  1. Confirm the media upload completed and the media object exists (query MediaObject/media comment by that id for the same user/context).
  2. Pass the media_id (kaltura-style m-... string), not a numeric attachment/file id.
  3. Re-upload the media if the object was deleted or never created, then retry the comment mutation.
  4. Omit media_object_id if no media comment is intended instead of sending an empty/invalid value.

Example fix

// before
const input = { submissionId, comment, mediaObjectId: attachmentId } // wrong id kind
// after
const media = await uploadAndGetMediaObject(file) // returns m-... media_id
if (!media) throw new Error('Upload failed; cannot attach media comment')
const input = { submissionId, comment, mediaObjectId: media.mediaId }
Defensive patterns

Strategy: validation

Validate before calling

if (mediaObjectId && !/^m-[A-Za-z0-9]+$/.test(mediaObjectId)) throw new Error('media_object_id must be a media id, not a file id')
// and confirm the upload completed before commenting
if (uploadPending) throw new Error('wait for media upload to finish')

Type guard

function isMediaObjectId(v) { return typeof v === 'string' && v.startsWith('m-') && v.length > 2 }

Try / catch

try {
  await gql(CREATE_SUBMISSION_COMMENT, { input })
} catch (e) {
  if (e.message === 'not found' && input.mediaObjectId) { dropMediaAndResendWithoutMedia() }
  else throw e
}

Prevention

When it happens

Trigger: Passing media_object_id that was never uploaded, was deleted, belongs to another user/course context, or is an attachment ID rather than a media_id (media_id is the 'm-<hash>' style identifier, not a numeric DB id).

Common situations: Recording/Studio upload flow failed silently so the media object never persisted; copying media IDs between courses; confusing canvas media_id with file/attachment ids.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/830f9a5630a3fca4. Report an issue: GitHub.

Appendix: source

Thrown at app/graphql/mutations/create_submission_comment.rb:54

  argument :submission_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("Submission")

  field :submission_comment, Types::SubmissionCommentType, null: true

  def resolve(input:)
    submission = Submission.find input[:submission_id]
    verify_authorized_action!(submission, :comment)

    latest_attempt = submission.context.feature_enabled?(:assignments_2_student) ? submission.attempt : nil
    opts = {
      attempt: input[:attempt] || latest_attempt,
      author: current_user,
      comment: input[:comment],
      draft_comment: input[:draft_comment]
    }

    if input[:media_object_id].present?
      media_objects = MediaObject.by_media_id(input[:media_object_id])
      raise GraphQL::ExecutionError, "not found" if media_objects.empty?

      opts[:media_comment_id] = input[:media_object_id]

      if input[:media_object_type].present?
        opts[:media_comment_type] = input[:media_object_type]
      end
    end

    file_ids = (input[:file_ids] || []).uniq
    unless file_ids.empty?
      attachments = Attachment.where(id: file_ids).to_a
      raise GraphQL::ExecutionError, "not found" unless attachments.length == file_ids.length

      attachments.each do |a|
        verify_authorized_action!(a, :attach_to_submission_comment)
        a.ok_for_submission_comment = true
      end
      opts[:attachments] = attachments

View on GitHub (pinned to 1c9f0bb801)