instructure/canvas-lms · error · PeerReview::InvalidDatesError

Peer review override available from date cannot be before…

Error message

Peer review override available from date cannot be before parent override due date

What it means

PeerReview::InvalidDatesError raised by validate_dates_within_parent_boundaries when the peer review's available-from date starts before the parent is even due. Canvas requires assignment due_at <= peer review unlock_at (peer reviews open only after the assignment is due). When the parent has a due_at, the message compares against it; the elsif branch (line 165, error 565) covers the fallback to parent unlock_at.

Solutions

  1. Set the peer review unlock_at to a timestamp >= parent assignment due_at
  2. Or move the parent assignment due_at earlier so reviews can open when intended
  3. If the parent should have no due gate, set parent due_at to nil so validation falls back to comparing against parent unlock_at
  4. Pre-validate: raise if parent.due_at && pr.due_at_pr... i.e. raise if parent.due_at > pr_unlock_at

Example fix

// before
assignment.update(due_at: '2026-05-10T00:00:00Z')
peer_review_dates = { unlock_at: '2026-05-01T00:00:00Z' }
// after
assignment.update(due_at: '2026-05-10T00:00:00Z')
peer_review_dates = { unlock_at: '2026-05-10T00:00:01Z' }
Defensive patterns

Strategy: validation

Validate before calling

def reviews_open_after_assignment_due?(parent, pr_dates)
  return true if parent.due_at.nil? || pr_dates[:unlock_at].nil?
  parent.due_at <= Time.zone.parse(pr_dates[:unlock_at].to_s)
end

Try / catch

begin
  validator.validate_peer_review_dates_against_parent_assignment(pr_dates, assignment)
rescue PeerReview::InvalidDatesError => e
  if e.message.include?('available from date cannot be before')
    pr_dates[:unlock_at] = assignment.due_at + 1.minute
    retry
  end
  raise
end

Prevention

When it happens

Trigger: Calling validate_peer_review_dates_against_parent_assignment with parent assignment due_at later than the peer review unlock_at, or validate_override_dates_against_parent_override where parent_due_at (due_at_overridden) > peer review override unlock_at. E.g. assignment due 2026-05-10, peer review unlock 2026-05-01.

Common situations: Scripts that copy the same unlock date to both assignment and peer review; teachers scheduling reviews to run alongside the assignment; override flows where the parent override due was extended after peer review dates were drafted.

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


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

Appendix: source

Thrown at app/services/peer_review/validations.rb:162

    end
  end

  def validate_dates_within_parent_boundaries(child_dates:, parent_unlock_at:, parent_due_at:, parent_lock_at:, is_override: false)
    child_unlock_at = parse_date(child_dates, :unlock_at)
    child_due_at = parse_date(child_dates, :due_at)
    child_lock_at = parse_date(child_dates, :lock_at)

    # Validate: parent unlock_at <= parent due_at
    if parent_unlock_at && parent_due_at && parent_unlock_at > parent_due_at
      raise PeerReview::InvalidDatesError,
            is_override ? I18n.t("Parent override due date cannot be before parent override available from date") : I18n.t("Assignment due date cannot be before assignment available from date")
    end

    # Validate: child unlock_at constraint
    # If parent_due_at is present, validate: parent due_at <= child unlock_at
    # Otherwise, fall back to: parent unlock_at <= child unlock_at
    if parent_due_at && child_unlock_at && parent_due_at > child_unlock_at
      raise PeerReview::InvalidDatesError,
            is_override ? I18n.t("Peer review override available from date cannot be before parent override due date") : I18n.t("Peer review available from date cannot be before assignment due date")
    elsif !parent_due_at && parent_unlock_at && child_unlock_at && parent_unlock_at > child_unlock_at
      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

View on GitHub (pinned to 1c9f0bb801)