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

  1. Check completed? && graded? before calling data; use temporary_data for in-progress submissions
  2. Wait for grading to complete (e.g. poll or defer job until graded) before reading data
  3. Distinguish unsubmitted vs ungraded states and surface an appropriate message to users
  4. 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

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


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)