instructure/canvas-lms · error · RuntimeError
Cannot view data for uncompleted quiz
Error message
Cannot view data for uncompleted quiz
What it means
QuizSubmission#data returns the UTF-8-cleaned submission_data but only for submissions that are both completed and graded. Calling it on an in-progress submission raises this guard error because the answers are still mutable and not final.
Solutions
- Check completed? && graded? before calling data; use temporary_data for in-progress submissions
- Wait for grading to complete (e.g. poll or defer job until graded) before reading data
- Distinguish unsubmitted vs ungraded states and surface an appropriate message to users
- Re-fetch the submission after submission/grading events if you hold a stale object
Example fix
// before answers = quiz_submission.data // after answers = quiz_submission.completed? && quiz_submission.graded? ? quiz_submission.data : quiz_submission.temporary_data
Defensive patterns
Strategy: validation
Validate before calling
unless qs.completed? && qs.graded? raise QuizSubmission::UnreadableData unless yield_ready?(qs) end
Type guard
readable_data = ->(qs) { qs.completed? && qs.graded? } Try / catch
begin answers = qs.data rescue RuntimeError answers = qs.temporary_data if !qs.completed? && !qs.graded? end
Prevention
- Only read #data in post-grading flows (reports, analytics, mastery paths)
- Defer background jobs until the submission is graded before reading data
- Differentiate 'not submitted' vs 'not graded' when messaging users
- Re-fetch the submission after submit/grade callbacks to avoid stale state
When it happens
Trigger: Calling quiz_submission.data when the student has not submitted (completed? false) or the submission is not yet graded (graded? false) — e.g. reading results during an active quiz attempt or before autograding finishes.
Common situations: Report/view code reading quiz answers while the student is still taking the quiz; jobs running before grading completes; OQAAT flows where the submission isn't finalized; results_visible? flows invoked too early.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot view temporary data for completed quiz
- Can't update submission scores unless it's completed
- Cannot set rubric self assessment for quiz assignments
- Could not find valid answer
- Could not find valid question
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/e93fa9d14066024a.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/quizzes/quiz_submission.rb:238
(submission_data || {}).with_indifferent_access
end
def question_answered?(id)
keys = temporary_data.keys.select do |key|
# find keys with answers for this question; skip question_x_marked and _read
(key =~ /question_#{id}(_|$)/) && key !~ /_(marked|read)$/
end
if keys.present?
all_present = keys.all? { |key| temporary_data[key].present? }
all_zeroes = keys.length > 1 && keys.all? { |key| temporary_data[key] == "0" }
all_present && !all_zeroes # all zeroes applies to multiple answer questions
end
end
def data
raise "Cannot view data for uncompleted quiz" unless completed?
raise "Cannot view data for uncompleted quiz" unless graded?
Utf8Cleaner.recursively_strip_invalid_utf8!(submission_data, force_utf8: true)
end
def results_visible?(user: nil)
return true unless quiz.present?
return true if quiz.grants_right?(user, :review_grades)
return false if quiz.restrict_answers_for_concluded_course?(user:)
return false if quiz.one_time_results && has_seen_results?
return false if quiz.hide_results == "always"
results_visible_for_attempt?
end
def results_visible_for_attempt?
return true unless quiz.hide_results == "until_after_last_attempt"
View on GitHub (pinned to 1c9f0bb801)