{"record":{"id":"62b579459ad425b7","repo":"instructure/canvas-lms","slug":"course-not-found-auto-grade-submission","errorCode":null,"errorMessage":"Course not found","messagePattern":"Course not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/auto_grade_submission.rb","lineNumber":40,"sourceCode":"  argument :submission_id, ID, required: true\n\n  field :error, String, null: true\n  field :progress, Types::ProgressType, null: true\n\n  def resolve(input:)\n    submission_id = GraphQLHelpers.parse_relay_or_legacy_id(input[:submission_id], \"Submission\")\n    submission = Submission.find(submission_id)\n\n    errors = []\n    GraphQLHelpers::AutoGradeEligibilityHelper.validate_assignment(assignment: submission.assignment).each { |i| append_issue_message(errors, i) }\n    GraphQLHelpers::AutoGradeEligibilityHelper.validate_submission(submission:).each { |i| append_issue_message(errors, i) }\n\n    if errors.any?\n      raise GraphQL::ExecutionError, \"Auto-grading failed due to the following issue(s): #{errors.join(\", \")}\"\n    end\n\n    course = submission.assignment&.course\n    raise \"Course not found\" unless course\n\n    unless course.feature_enabled?(:project_lhotse)\n      raise GraphQL::ExecutionError, I18n.t(\"Project Lhotse is not enabled for this course.\")\n    end\n\n    verify_authorized_action!(course, :manage_grades)\n\n    service = AutoGradeOrchestrationService.new(course:, current_user:)\n    progress = service.auto_grade_in_background(submission:)\n\n    { progress: }\n  rescue GraphQL::ExecutionError => e\n    Rails.logger.error(\"[AutoGradeSubmission GraphQL ExecutionError] #{e.message}\")\n    raise e\n  rescue => e\n    Rails.logger.error(\"[AutoGradeSubmission ERROR] #{e.message}\")\n    raise GraphQL::ExecutionError, I18n.t(\"An unexpected error occurred while grading.\")\n  end","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/auto_grade_submission.rb#L22-L58","documentation":"In the AutoGradeSubmission GraphQL mutation, resolve raises a plain 'Course not found' RuntimeError when submission.assignment&.course is nil — the assignment is not attached to a course (e.g. standalone/sub-assignment context) or was deleted, so authorization and feature checks cannot proceed.","triggerScenarios":"Calling autoGradeSubmission for a submission whose assignment has no course association (assignment belongs to a deleted course, an orphaned assignment, or assignment nil despite earlier checks).","commonSituations":"Sub-assignments/checkpoint setups where the parent object was deleted; data inconsistencies after course deletion; mutation invoked on an assignment in a non-course context.","solutions":["Verify the submission id refers to a submission on a live course assignment","Pre-check in the client: load assignment.course before calling the mutation and surface a friendly error","Restore the deleted course/assignment if it was removed unintentionally","Change the mutation to raise GraphQL::ExecutionError instead of RuntimeError for a cleaner GraphQL error payload"],"exampleFix":"# before\nraise \"Course not found\" unless course\n# after\nraise GraphQL::ExecutionError, \"Course not found for assignment\" unless course","handlingStrategy":"validation","validationCode":"const submission = await canvas.get(`/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`);\nif (!submission?.assignment?.course_id) {\n  throw new Error('Submission has no course assignment; cannot auto-grade');\n}","typeGuard":"function isCourseSubmission(sub) {\n  return sub != null && sub.assignment != null && typeof sub.assignment.course_id === 'number' && sub.assignment.course_id > 0;\n}","tryCatchPattern":"try {\n  await autoGradeSubmission({ submissionId });\n} catch (e) {\n  if (e.message === 'Course not found') {\n    showError('This submission no longer belongs to a course; refresh and retry.');\n  }\n}","preventionTips":["Verify assignment.course_id before invoking the mutation","Refresh submission data after any course/assignment deletion","Guard UI entry points so auto-grade is only offered on live course assignments","Watch for checkpoint/sub-assignment data inconsistencies in test environments"],"tags":["graphql","mutation","courses"],"backgroundTag":"resource-not-found","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"}