instructure/canvas-lms · error · PeerReview::InvalidDatesError
Peer review due date cannot be after assignment until date
Error message
Peer review due date cannot be after assignment until date
What it means
PeerReview::InvalidDatesError raised by validate_dates_within_parent_boundaries for the non-override path: the peer review due_at is after the parent assignment's until (lock_at) date. Canvas requires assignment due/until boundaries to contain peer review dates. Same check as error 570 but with is_override=false.
Solutions
- Lower the peer review due_at to be <= assignment.lock_at
- Raise assignment.lock_at (or leave it nil) so it bounds the peer review due date
- Re-run the service after fixing the date ordering
Example fix
// before
peer_review_dates = { due_at: Time.zone.parse('2026-11-01') }
assignment.lock_at = Time.zone.parse('2026-10-15')
// after
peer_review_dates = { due_at: Time.zone.parse('2026-10-10') }
assignment.lock_at = Time.zone.parse('2026-10-15') Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, 'peer review due_at must be <= assignment.lock_at' if pr_dates[:due_at] && assignment.lock_at && pr_dates[:due_at] > assignment.lock_at
Try / catch
begin service.validate_peer_review_dates_against_parent_assignment(dates, assignment) rescue PeerReview::InvalidDatesError => e Rails.logger.warn(e.message) flash[:error] = e.message end
Prevention
- Compute peer review dates from the assignment dates (e.g. due_at = assignment.lock_at - 1.day) instead of hardcoding
- Re-run date validation whenever assignment lock_at changes
- Leave assignment.lock_at nil when no hard until boundary is intended
When it happens
Trigger: Calling validate_peer_review_dates_against_parent_assignment (via PeerReviewCommonService) with peer_review_dates.due_at > parent_assignment.lock_at; also reachable via validate_override_dates_against_parent_override when is_override is false is not possible, so this variant comes from assignment-level peer review date validation.
Common situations: Backdating an assignment lock_at after peer review dates were set; syncing due dates via API without adjusting peer review subassignment dates.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Peer review override due date cannot be after parent…
- Course does not exist
- Override does not exist
- Section does not exist
- Set id is required
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/933a1546eec953cf.
Report an issue: GitHub.
Appendix: source
Thrown at app/services/peer_review/validations.rb:189
raise PeerReview::InvalidDatesError,
is_override ? I18n.t("Peer review override due date cannot be before parent override available from date") : I18n.t("Peer review due date cannot be before assignment available from date")
end
# Validate: parent due_at <= child due_at
if parent_due_at && child_due_at && parent_due_at > child_due_at
raise PeerReview::InvalidDatesError,
is_override ? I18n.t("Peer review override due date cannot be before parent override due date") : I18n.t("Peer review due date cannot be before assignment due date")
end
# Validate: child due_at <= parent lock_at
if child_due_at && parent_lock_at && child_due_at > parent_lock_at
raise PeerReview::InvalidDatesError,
is_override ? I18n.t("Peer review override due date cannot be after parent override until date") : I18n.t("Peer review due date cannot be after assignment until date")
end
# Validate: child lock_at <= parent lock_at
if child_lock_at && parent_lock_at && child_lock_at > parent_lock_at
raise PeerReview::InvalidDatesError,
is_override ? I18n.t("Peer review override until date cannot be after parent override until date") : I18n.t("Peer review until date cannot be after assignment until date")
end
end
def validate_set_type_required(set_type)
raise PeerReview::SetTypeRequiredError, I18n.t("Set type is required") unless set_type.present?
end
def validate_set_id_required(set_id)
raise PeerReview::SetIdRequiredError, I18n.t("Set id is required") unless set_id.present?
end
def validate_override_exists(override)
raise PeerReview::OverrideNotFoundError, I18n.t("Override does not exist") unless override.present?
end
def validate_section_exists(section)
raise PeerReview::SectionNotFoundError, I18n.t("Section does not exist") unless section.present?View on GitHub (pinned to 1c9f0bb801)