instructure/canvas-lms · error · RuntimeError
Cannot view temporary data for completed quiz
Error message
Cannot view temporary data for completed quiz
What it means
QuizSubmission#temporary_data returns the in-progress (ungraded, uncompleted) submission_data hash and raises if the quiz submission is already completed. Once a submission is finalized its data is no longer 'temporary', so reading it via this method is invalid — use #data or graded methods instead.
Solutions
- Check quiz_submission.completed? before calling temporary_data and use #data for finished submissions
- Re-fetch the submission's current state if you cached the object across a request
- Handle the transition: design consumers to accept either temporary_data (in-progress) or data (completed)
- For live views, catch the error and refresh the submission state
Example fix
// before answers = quiz_submission.temporary_data // after answers = quiz_submission.completed? || quiz_submission.graded? ? quiz_submission.data : quiz_submission.temporary_data
Defensive patterns
Strategy: validation
Validate before calling
raise 'submission not finalized' unless qs.completed? || qs.graded? # choose accessor: answers = (qs.completed? || qs.graded?) ? qs.data : qs.temporary_data
Type guard
in_progress = ->(qs) { !qs.completed? && !qs.graded? } Try / catch
begin answers = qs.temporary_data rescue RuntimeError answers = qs.data end
Prevention
- Re-load the quiz submission before reading its state in polling flows
- Branch on completed?/graded? before choosing between temporary_data and data
- Watch for timed auto-submissions that finalize submissions mid-job
- Add state checks in live-update endpoints to handle just-submitted quizzes
When it happens
Trigger: Calling quiz_submission.temporary_data when the submission's workflow_state indicates completed (student submitted the quiz or it was auto-submitted), before any graded? check passes.
Common situations: Live-updating UI code polling a submission that the student just submitted; background job reading in-progress answers after a timed auto-submission; controller code not re-checking submission state between calls.
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 data for uncompleted 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/1664f950405e480a.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/quizzes/quiz_submission.rb:217
question_key = "question_#{question_id}"
if submission_data[question_key]
submission_data[question_key] = Sanitize.clean(submission_data[question_key] || "", CanvasSanitize::SANITIZE)
end
end
end
true
end
def question(id)
questions.detect { |q| q[:id].to_i == id.to_i }
end
def has_question?(id)
question(id).present?
end
def temporary_data
raise "Cannot view temporary data for completed quiz" if completed?
raise "Cannot view temporary data for completed quiz" if graded?
(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
endView on GitHub (pinned to 1c9f0bb801)