instructure/canvas-lms · error · MissingPeerReviewSubmissionError

Submission is missing for PeerReviewSubAssignment

Error message

Submission is missing for PeerReviewSubAssignment %{assignment_id} and user %{user_id}

What it means

PeerReview::PeerReviewSubmissionSerializer resolves the submission for a peer-review sub-assignment and user. If the peer review submission is absent and no submission has ever existed for that sub_assignment/user, it raises MissingPeerReviewSubmissionError (I18n-formatted with assignment_id and user_id). Peer review workflows require a submission record for each reviewer/target user.

Solutions

  1. Ensure the target student has a submission on the parent assignment so the peer review sub-assignment submission gets created.
  2. Create the missing submission shell for the user on the peer review sub-assignment before serializing.
  3. Catch MissingPeerReviewSubmissionError and render an empty/default peer review payload.
  4. Verify reviewer assignment/user_id correctness; only serialize for users actually assigned to the peer review.

Example fix

// before
PeerReview::PeerReviewSubmissionSerializer.new(peer_review_sub_assignment, user_id).as_json
# => MissingPeerReviewSubmissionError

// after
unless Submission.unscoped.exists?(assignment_id: peer_review_sub_assignment.id, user_id: user_id)
  peer_review_sub_assignment.submissions.create!(user_id: user_id)
end
PeerReview::PeerReviewSubmissionSerializer.new(peer_review_sub_assignment, user_id).as_json
Defensive patterns

Strategy: try-catch

Validate before calling

unless Submission.unscoped.exists?(assignment_id: peer_review_sub_assignment.id, user_id: user_id)
  peer_review_sub_assignment.submissions.create!(user_id: user_id)
end

Type guard

def peer_review_submission_exists?(pr_sub_assignment, user_id)
  Submission.unscoped.exists?(assignment_id: pr_sub_assignment.id, user_id: user_id)
end

Try / catch

begin
  serializer.as_json
rescue Checkpoints::MissingPeerReviewSubmissionError => e
  Rails.logger.info(e.message)
  { peer_review_submission: nil }
end

Prevention

When it happens

Trigger: Serialize a peer review sub-assignment submission for a user_id with zero Submission rows where assignment_id == peer_review_sub_assignment.id (peer review created before submissions were seeded, or reviewer never interacted).

Common situations: Peer review of a student who never submitted the parent assignment, so no submission was cloned for review; API/serialization calls for reviewers not assigned to the peer review; course copy/import dropping submission records.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/d6fcd370a32aeb05. Report an issue: GitHub.

Appendix: source

Thrown at app/serializers/peer_review/peer_review_submission_serializer.rb:50

    {
      has_peer_review_submission: submission.present?,
      submission:
    }
  end

  def self.find_peer_review_submission(peer_review_sub_assignment, user_id)
    peer_review_submission = peer_review_sub_assignment.submissions.where(user_id:)
                                                       .where(workflow_state: %w[submitted graded])
                                                       .first

    if peer_review_submission.present?
      peer_review_submission
    else
      any_submission_ever = Submission.unscoped.find_by(assignment_id: peer_review_sub_assignment.id, user_id:)

      if any_submission_ever.nil?
        raise MissingPeerReviewSubmissionError, I18n.t("Submission is missing for PeerReviewSubAssignment %{assignment_id} and user %{user_id}",
                                                       assignment_id: peer_review_sub_assignment.id,
                                                       user_id:)
      else
        nil
      end
    end
  end
end

View on GitHub (pinned to 1c9f0bb801)