{"record":{"id":"f07ad62f941815db","repo":"instructure/canvas-lms","slug":"peer-review-override-due-date-cannot-be-after-parent","errorCode":null,"errorMessage":"Peer review override due date cannot be after parent override until date","messagePattern":"Peer review override due date cannot be after parent override until date","errorType":"validation","errorClass":"PeerReview::InvalidDatesError","httpStatus":null,"severity":"error","filePath":"app/services/peer_review/validations.rb","lineNumber":189,"sourceCode":"      raise PeerReview::InvalidDatesError,\n            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\")\n    end\n\n    # Validate: parent due_at <= child due_at\n    if parent_due_at && child_due_at && parent_due_at > child_due_at\n      raise PeerReview::InvalidDatesError,\n            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\")\n    end\n\n    # Validate: child due_at <= parent lock_at\n    if child_due_at && parent_lock_at && child_due_at > parent_lock_at\n      raise PeerReview::InvalidDatesError,\n            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\")\n    end\n\n    # Validate: child lock_at <= parent lock_at\n    if child_lock_at && parent_lock_at && child_lock_at > parent_lock_at\n      raise PeerReview::InvalidDatesError,\n            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\")\n    end\n  end\n\n  def validate_set_type_required(set_type)\n    raise PeerReview::SetTypeRequiredError, I18n.t(\"Set type is required\") unless set_type.present?\n  end\n\n  def validate_set_id_required(set_id)\n    raise PeerReview::SetIdRequiredError, I18n.t(\"Set id is required\") unless set_id.present?\n  end\n\n  def validate_override_exists(override)\n    raise PeerReview::OverrideNotFoundError, I18n.t(\"Override does not exist\") unless override.present?\n  end\n\n  def validate_section_exists(section)\n    raise PeerReview::SectionNotFoundError, I18n.t(\"Section does not exist\") unless section.present?","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/peer_review/validations.rb#L171-L207","documentation":"PeerReview::InvalidDatesError raised by PeerReview::Validations#validate_dates_within_parent_boundaries when a child due_at exceeds the parent's lock_at (until) date. When is_override is true the peer review override due date is later than the parent assignment override's until date; otherwise the peer review due date is later than the parent assignment's until date. Canvas enforces the ordering assignment until date >= peer review due date so reviews are locked before the assignment.","triggerScenarios":"Calling a peer review service that runs validate_override_dates_against_parent_override (creating/updating a peer review override whose due_at > parent override lock_at with lock_at_overridden) or validate_peer_review_dates_against_parent_assignment (setting peer_review_dates.due_at after parent_assignment.lock_at). The message variant depends on is_override.","commonSituations":"Setting an assignment lock_at earlier than the peer review due date; extending a peer review due date after the parent override's until date was already set; importing/copying assignments with shifted date ranges.","solutions":["Set the peer review due_at to be on or before the parent (override) lock_at/until date","Extend the parent assignment override's lock_at (with lock_at_overridden=true) so it is >= the peer review due date","Clear the parent lock_at if no hard until boundary is needed"],"exampleFix":"// before\n{ peer_review: { due_at: '2026-10-10', assignment: { lock_at: '2026-10-01' } } }\n// after\n{ peer_review: { due_at: '2026-09-30', assignment: { lock_at: '2026-10-01' } } }","handlingStrategy":"validation","validationCode":"raise ArgumentError, 'peer review due_at must be <= assignment lock_at' if peer.due_at && parent.lock_at && peer.due_at > parent.lock_at","typeGuard":null,"tryCatchPattern":"begin\n  PeerReview::Service.call(...)\nrescue PeerReview::InvalidDatesError => e\n  render json: { error: e.message }, status: :unprocessable_entity\nend","preventionTips":["Keep the ordering: assignment unlock_at <= assignment due_at <= peer review due_at <= peer review until date <= assignment lock_at","When editing any one date, re-validate the whole date chain","Never set a parent lock_at earlier than an existing peer review due date"],"tags":["ruby","peer-review","date-validation","canvas"],"backgroundTag":"value-out-of-range","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}