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

An unexpected error occurred while grading.

Error message

An unexpected error occurred while grading.

What it means

AutoGradeSubmission's resolve wraps its grading logic in a catch-all rescue. Any non-GraphQL error raised during the mutation (e.g. inside the AutoGrade service, model callbacks, or I18n/network calls) is logged and re-raised as a GraphQL::ExecutionError with the generic message 'An unexpected error occurred while grading.' This is a deliberately opaque internal-failure guard so no internal details leak to API consumers.

Solutions

  1. Check server logs for the '[AutoGradeSubmission ERROR]' line to see the real exception message
  2. Reproduce the grading call in rails console to surface the underlying exception
  3. Confirm the submission/assignment exists and is in a gradable state
  4. If the real cause is expected, rescue it specifically in resolve and return a meaningful GraphQL::ExecutionError

Example fix

// before
raise GraphQL::ExecutionError, I18n.t("An unexpected error occurred while grading.")
// after
rescue AutoGrade::ServiceUnavailable => e
  raise GraphQL::ExecutionError, I18n.t("Grading service unavailable, try again later.")
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check before calling the mutation
const submission = await canvas.get(`/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`)
if (!submission || submission.workflow_state === 'unsubmitted') throw new Error('nothing to grade')

Type guard

function isGradingResult(r) { return r != null && typeof r.progress === 'object' && r.progress != null && r.progress.id != null }

Try / catch

try {
  await client.mutate({ mutation: AUTO_GRADE_SUBMISSION, variables: { id } })
} catch (e) {
  if (e.message.includes('An unexpected error occurred while grading')) {
    // check server logs for real cause; surface retry-able UI
  }
  throw e
}

Prevention

When it happens

Trigger: Calling mutation autoGradeSubmission when any standard (non-GraphQL::ExecutionError) exception escapes resolve: AutoGrade service raising, ActiveRecord errors not wrapped as ExecutionError, nil progress target, or any bug in grading callbacks.

Common situations: Grading service misconfiguration, feature-flagged AI grading backend unavailable, invalid submission state hitting model validations mid-transaction, or version drift where the service returns nil and downstream code calls a method on it.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at app/graphql/mutations/auto_grade_submission.rb:57

    course = submission.assignment&.course
    raise "Course not found" unless course

    unless course.feature_enabled?(:project_lhotse)
      raise GraphQL::ExecutionError, I18n.t("Project Lhotse is not enabled for this course.")
    end

    verify_authorized_action!(course, :manage_grades)

    service = AutoGradeOrchestrationService.new(course:, current_user:)
    progress = service.auto_grade_in_background(submission:)

    { progress: }
  rescue GraphQL::ExecutionError => e
    Rails.logger.error("[AutoGradeSubmission GraphQL ExecutionError] #{e.message}")
    raise e
  rescue => e
    Rails.logger.error("[AutoGradeSubmission ERROR] #{e.message}")
    raise GraphQL::ExecutionError, I18n.t("An unexpected error occurred while grading.")
  end

  def append_issue_message(errors, issue)
    errors << issue[:message] if issue && issue[:level] == "error"
  end
end

View on GitHub (pinned to 1c9f0bb801)