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
- Check server logs for the '[AutoGradeSubmission ERROR]' line to see the real exception message
- Reproduce the grading call in rails console to surface the underlying exception
- Confirm the submission/assignment exists and is in a gradable state
- 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
- Always check the '[AutoGradeSubmission ERROR]' log line to diagnose, since the client message is generic
- Ensure the submission is in a gradable state before invoking
- Keep the AutoGrade backend service and feature flags verified in each environment
- Wrap known service failures in specific rescues so they don't fall into the catch-all
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
- An unexpected error occurred while submitting feedback.
- All ConversationMessages must exist within the same…
- Assignment Grade Error
- Assignment not found
- Assignment not found
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)