{"record":{"id":"e93fa9d14066024a","repo":"instructure/canvas-lms","slug":"cannot-view-data-for-uncompleted-quiz","errorCode":null,"errorMessage":"Cannot view data for uncompleted quiz","messagePattern":"Cannot view data for uncompleted quiz","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"app/models/quizzes/quiz_submission.rb","lineNumber":238,"sourceCode":"    (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\n\n  def data\n    raise \"Cannot view data for uncompleted quiz\" unless completed?\n    raise \"Cannot view data for uncompleted quiz\" unless graded?\n\n    Utf8Cleaner.recursively_strip_invalid_utf8!(submission_data, force_utf8: true)\n  end\n\n  def results_visible?(user: nil)\n    return true unless quiz.present?\n    return true if quiz.grants_right?(user, :review_grades)\n    return false if quiz.restrict_answers_for_concluded_course?(user:)\n    return false if quiz.one_time_results && has_seen_results?\n    return false if quiz.hide_results == \"always\"\n\n    results_visible_for_attempt?\n  end\n\n  def results_visible_for_attempt?\n    return true unless quiz.hide_results == \"until_after_last_attempt\"\n","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/quizzes/quiz_submission.rb#L220-L256","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nanswers = quiz_submission.data\n// after\nanswers = quiz_submission.completed? && quiz_submission.graded? ? quiz_submission.data : quiz_submission.temporary_data\n","handlingStrategy":"validation","validationCode":"unless qs.completed? && qs.graded?\n  raise QuizSubmission::UnreadableData unless yield_ready?(qs)\nend","typeGuard":"readable_data = ->(qs) { qs.completed? && qs.graded? }","tryCatchPattern":"begin\n  answers = qs.data\nrescue RuntimeError\n  answers = qs.temporary_data if !qs.completed? && !qs.graded?\nend","preventionTips":["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"],"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"}