instructure/canvas-lms · error · PeerReview::InvalidDatesError
Peer review due date cannot be before assignment due date
Error message
Peer review due date cannot be before assignment due date
What it means
PeerReview::InvalidDatesError — the non-override (is_override: false) wording of the parent due_at <= child due_at check in validate_dates_within_parent_boundaries: 'Peer review due date cannot be before assignment due date'. Raised when peer review sub assignment dates are validated against the parent assignment (validate_peer_review_dates_against_parent_assignment) and the peer review due_at precedes the parent assignment's due_at, violating the required ordering assignment due <= peer review due.
Solutions
- Set the peer review due_at to >= parent_assignment.due_at
- Or lower parent_assignment.due_at so reviews can be due when intended
- Clear peer review due_at (nil) if reviews only need an until date
- Pre-validate in the caller: raise if assignment.due_at && pr.due_at && assignment.due_at > pr.due_at
Example fix
// before
parent_assignment.due_at # 2026-05-15T00:00:00Z
peer_review_dates = { due_at: '2026-05-10T00:00:00Z' }
// after
peer_review_dates = { due_at: '2026-05-16T00:00:00Z' } Defensive patterns
Strategy: validation
Validate before calling
def review_due_on_or_after_assignment_due?(assignment, pr_dates) return true if assignment.due_at.nil? || pr_dates[:due_at].nil? assignment.due_at <= Time.zone.parse(pr_dates[:due_at].to_s) end
Try / catch
begin
PeerReviewService.create(assignment:, peer_review_dates: pr_dates)
rescue PeerReview::InvalidDatesError => e
raise unless e.message == I18n.t('Peer review due date cannot be before assignment due date')
pr_dates[:due_at] = assignment.due_at
retry
end Prevention
- Enforce the ordering assignment due_at <= review due_at in your scheduling code
- Derive review due from assignment due (+ offset) instead of storing independent dates
- After any assignment due_at update, validate existing peer review dates still satisfy the chain
- Cover both override and non-override paths in tests, since wording and sources differ
When it happens
Trigger: Calling validate_peer_review_dates_against_parent_assignment(peer_review_dates, parent_assignment) with parent_assignment.due_at present and peer review dates' due_at strictly earlier, e.g. assignment due 2026-05-15, peer review due 2026-05-10.
Common situations: API integrations that schedule peer reviews before the assignment closes; clients reusing one date set for both assignment and reviews when the assignment due was later extended; tests with fixture dates in the wrong order.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Parent override due date cannot be before parent override…
- Peer review override available from date cannot be before…
- Peer review override available from date cannot be before…
- Peer review override due date cannot be before parent…
- Peer review override due date cannot be before parent…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/f5f5e6df57c6b63c.
Report an issue: GitHub.
Appendix: source
Thrown at app/services/peer_review/validations.rb:183
raise PeerReview::InvalidDatesError,
is_override ? I18n.t("Peer review override available from date cannot be before parent override available from date") : I18n.t("Peer review available from date cannot be before assignment available from date")
end
# Validate: parent unlock_at <= child due_at (for backward compatibility)
if parent_unlock_at && child_due_at && parent_unlock_at > child_due_at
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
View on GitHub (pinned to 1c9f0bb801)