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
- Confirm the media upload completed and the media object exists (query MediaObject/media comment by that id for the same user/context).
- Pass the media_id (kaltura-style m-... string), not a numeric attachment/file id.
- Re-upload the media if the object was deleted or never created, then retry the comment mutation.
- 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
- Gate comment submission on successful media upload confirmation.
- Distinguish media ids (m-...) from attachment/file numeric ids.
- Keep media objects within the same user/context as the comment.
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] = attachmentsView on GitHub (pinned to 1c9f0bb801)