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

  1. Check quiz_submission.completed? before calling temporary_data and use #data for finished submissions
  2. Re-fetch the submission's current state if you cached the object across a request
  3. Handle the transition: design consumers to accept either temporary_data (in-progress) or data (completed)
  4. 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

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


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
  end

View on GitHub (pinned to 1c9f0bb801)