{"record":{"id":"1664f950405e480a","repo":"instructure/canvas-lms","slug":"cannot-view-temporary-data-for-completed-quiz","errorCode":null,"errorMessage":"Cannot view temporary data for completed quiz","messagePattern":"Cannot view temporary data for completed quiz","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"app/models/quizzes/quiz_submission.rb","lineNumber":217,"sourceCode":"        question_key = \"question_#{question_id}\"\n        if submission_data[question_key]\n          submission_data[question_key] = Sanitize.clean(submission_data[question_key] || \"\", CanvasSanitize::SANITIZE)\n        end\n      end\n    end\n    true\n  end\n\n  def question(id)\n    questions.detect { |q| q[:id].to_i == id.to_i }\n  end\n\n  def has_question?(id)\n    question(id).present?\n  end\n\n  def temporary_data\n    raise \"Cannot view temporary data for completed quiz\" if completed?\n    raise \"Cannot view temporary data for completed quiz\" if graded?\n\n    (submission_data || {}).with_indifferent_access\n  end\n\n  def question_answered?(id)\n    keys = temporary_data.keys.select do |key|\n      # find keys with answers for this question; skip question_x_marked and _read\n      (key =~ /question_#{id}(_|$)/) && key !~ /_(marked|read)$/\n    end\n\n    if keys.present?\n      all_present = keys.all? { |key| temporary_data[key].present? }\n      all_zeroes = keys.length > 1 && keys.all? { |key| temporary_data[key] == \"0\" }\n\n      all_present && !all_zeroes # all zeroes applies to multiple answer questions\n    end\n  end","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/quizzes/quiz_submission.rb#L199-L235","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nanswers = quiz_submission.temporary_data\n// after\nanswers = quiz_submission.completed? || quiz_submission.graded? ? quiz_submission.data : quiz_submission.temporary_data\n","handlingStrategy":"validation","validationCode":"raise 'submission not finalized' unless qs.completed? || qs.graded?\n# choose accessor:\nanswers = (qs.completed? || qs.graded?) ? qs.data : qs.temporary_data","typeGuard":"in_progress = ->(qs) { !qs.completed? && !qs.graded? }","tryCatchPattern":"begin\n  answers = qs.temporary_data\nrescue RuntimeError\n  answers = qs.data\nend","preventionTips":["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"],"tags":["quizzes","quiz-submission","lifecycle"],"backgroundTag":"invalid-state-transition","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"}