instructure/canvas-lms · error · PeerReview::SubAssignmentNotExistError
Peer review sub assignment does not exist
Error message
Peer review sub assignment does not exist
What it means
PeerReview::Validations#validate_peer_review_sub_assignment_exists raises PeerReview::SubAssignmentNotExistError when `assignment.peer_review_sub_assignment` is blank, i.e. the operation expects an existing peer review sub assignment (typically update/delete flows) but none has been created yet.
Solutions
- Create the sub assignment first via the creation service, then update it.
- Guard update/delete calls with `assignment.peer_review_sub_assignment.present?` and no-op (or create) when absent.
- Reconcile data: run the backfill that creates sub assignments for assignments with peer_reviews enabled.
Example fix
// before PeerReview::SubAssignmentUpdater.new(assignment: assignment).call # no sub assignment yet // after if assignment.peer_review_sub_assignment.blank? PeerReview::SubAssignmentCreator.new(assignment: assignment).call end PeerReview::SubAssignmentUpdater.new(assignment: assignment).call
Defensive patterns
Strategy: validation
Validate before calling
return render json: { error: "no sub assignment" }, status: :not_found if assignment.peer_review_sub_assignment.blank? Type guard
def sub_assignment_exists?(assignment) = assignment.peer_review_sub_assignment.present?
Try / catch
begin updater.call rescue PeerReview::SubAssignmentNotExistError create_sub_assignment(assignment) end
Prevention
- Create the sub assignment before scheduling update/delete jobs
- Use present?/blank? guards on peer_review_sub_assignment
- Backfill sub assignments for legacy peer-review-enabled assignments
When it happens
Trigger: Updating or deleting the peer review sub assignment of an assignment that never had one created; calling sync/update services before SubAssignmentCreator ran; the sub assignment having been deleted earlier.
Common situations: Race between sub assignment deletion and an update job; feature flag turned on later so legacy assignments have no sub assignment; re-running migrations/sync scripts on fresh assignments.
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
- Due date cannot be before available from date
- Invalid parent assignment
- Must be a group assignment to create group overrides
- Peer review sub assignment exists
- Peer review sub assignments cannot have a not_graded…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/0234885007ed4a69.
Report an issue: GitHub.
Appendix: source
Thrown at app/services/peer_review/validations.rb:55
end
def validate_grading_type(grading_type)
raise PeerReview::InvalidGradingTypeError, I18n.t("Peer review sub assignments cannot have a not_graded grading type") if grading_type == "not_graded"
end
def validate_assignment_submission_types(assignment)
if assignment.external_tool?
raise PeerReview::InvalidAssignmentSubmissionTypesError, I18n.t("Peer reviews cannot be used with External Tool assignments")
end
if assignment.submission_types == "discussion_topic"
raise PeerReview::InvalidAssignmentSubmissionTypesError, I18n.t("Peer reviews cannot be used with Discussion Topic assignments")
end
end
def validate_peer_review_sub_assignment_exists(assignment)
if assignment.peer_review_sub_assignment.blank?
raise PeerReview::SubAssignmentNotExistError, I18n.t("Peer review sub assignment does not exist")
end
end
def validate_peer_review_sub_assignment_not_exist(assignment)
if assignment.peer_review_sub_assignment.present?
raise PeerReview::SubAssignmentExistsError, I18n.t("Peer review sub assignment exists")
end
end
# Validates that peer review dates follow the restriction below
# peer review unlock_at < peer review due_at <= peer review lock_at
def validate_peer_review_dates(peer_review_dates)
parsed_dates = {}
%w[due_at unlock_at lock_at].each do |date_field|
date_value = peer_review_dates.fetch(date_field.to_sym, nil)
next unless date_value.present?
View on GitHub (pinned to 1c9f0bb801)