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

Parent override due date cannot be before parent override…

Error message

Parent override due date cannot be before parent override available from date

What it means

PeerReview::InvalidDatesError raised by validate_dates_within_parent_boundaries when the parent's own available-from date (unlock_at) is later than its due date. For overrides this reports 'Parent override due date cannot be before parent override available from date'; for the plain assignment path it reports the assignment wording. The parent's dates are checked first because child peer review dates are only meaningful relative to a coherent parent window.

Solutions

  1. Fix the parent assignment/override: set unlock_at <= due_at before creating the peer review
  2. Update the parent override record (AssignmentOverride unlock_at/due_at) so its window is ordered
  3. If the parent legitimately has no due date, clear due_at (nil) so only unlock constraints apply
  4. Pre-check parent dates in code: raise if parent.unlock_at && parent.due_at && parent.unlock_at > parent.due_at

Example fix

// before
parent_override.update(unlock_at: '2026-05-10T00:00:00Z', due_at: '2026-05-01T00:00:00Z')
create_peer_review_override(parent_override, ...)
// after
parent_override.update(unlock_at: '2026-05-01T00:00:00Z', due_at: '2026-05-10T00:00:00Z')
create_peer_review_override(parent_override, ...)
Defensive patterns

Strategy: validation

Validate before calling

def parent_window_ordered?(parent)
  u, d = parent.unlock_at, parent.due_at
  !(u && d && u > d)
end
raise 'parent dates inverted' unless parent_window_ordered?(parent_override)

Try / catch

begin
  create_peer_review_for(parent_override)
rescue PeerReview::InvalidDatesError => e
  if e.message.include?('Parent override')
    fix_parent_dates!(parent_override)
    retry
  end
  raise
end

Prevention

When it happens

Trigger: Calling validate_override_dates_against_parent_override with a parent_override whose due_at_overridden date precedes its unlock_at_overridden date, or validate_peer_review_dates_against_parent_assignment with a parent assignment whose unlock_at > due_at — even if the peer review dates themselves are fine.

Common situations: Imported assignment overrides with inconsistent dates; a parent assignment edited to start later without moving its due date; seed/test fixtures with arbitrary dates; APIs accepting parent override updates without their own validation.

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

Appendix: source

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

      parsed = Time.zone.parse(date_value)
      if parsed.nil?
        raise PeerReview::InvalidDatesError,
              I18n.t("Invalid date format for %{field}: %{value}", field:, value: date_value)
      end
      parsed
    else
      date_value
    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")

View on GitHub (pinned to 1c9f0bb801)