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

Peer review override due date cannot be before parent…

Error message

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

What it means

PeerReview::InvalidDatesError from the backward-compatibility check in validate_dates_within_parent_boundaries: the peer review's due date must not precede the parent's available-from date. Override wording: 'Peer review override due date cannot be before parent override available from date'; assignment wording: 'Peer review due date cannot be before assignment available from date'. This catches pathologically wrong payloads where the review closes before the parent even opens.

Solutions

  1. Set the peer review due_at to a timestamp >= parent (override) unlock_at
  2. Or clear the peer review due_at if reviews need no deadline
  3. Fix swapped fields: verify due_at/unlock_at were not transposed in the payload
  4. Pre-validate: raise if parent.unlock_at && child.due_at && parent.unlock_at > child.due_at

Example fix

// before
peer_review_dates = { unlock_at: '2026-05-10T00:00:00Z', due_at: '2026-04-15T00:00:00Z' } # parent unlock 2026-05-01
// after
peer_review_dates = { unlock_at: '2026-05-10T00:00:00Z', due_at: '2026-05-20T00:00:00Z' }
Defensive patterns

Strategy: validation

Validate before calling

def review_due_after_parent_opens?(parent, pr_dates)
  return true if parent.unlock_at.nil? || pr_dates[:due_at].nil?
  parent.unlock_at <= Time.zone.parse(pr_dates[:due_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?('due date cannot be before assignment available')
    pr_dates[:due_at] = [assignment.unlock_at, pr_dates[:due_at]].compact.max
    retry
  end
  raise
end

Prevention

When it happens

Trigger: Calling validate_peer_review_dates_against_parent_assignment or validate_override_dates_against_parent_override with parent unlock_at set and child due_at < parent unlock_at, e.g. parent available 2026-05-01 but peer review due 2026-04-15.

Common situations: Copy-paste of peer review dates from a previous term while parent dates moved forward; swapped due_at/unlock_at fields in an API client; overrides built programmatically with default epoch-ish dates.

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/d8cb59870699be00. Report an issue: GitHub.

Appendix: source

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

    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

    # 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,

View on GitHub (pinned to 1c9f0bb801)