{"record":{"id":"23a53d94c0822501","repo":"instructure/canvas-lms","slug":"peer-review-override-due-date-cannot-be-before-parent-23a53d","errorCode":null,"errorMessage":"Peer review override due date cannot be before parent override due date","messagePattern":"Peer review override due date cannot be before parent override due date","errorType":"validation","errorClass":"PeerReview::InvalidDatesError","httpStatus":null,"severity":"error","filePath":"app/services/peer_review/validations.rb","lineNumber":177,"sourceCode":"    # If parent_due_at is present, validate: parent due_at <= child unlock_at\n    # Otherwise, fall back to: parent unlock_at <= child unlock_at\n    if parent_due_at && child_unlock_at && parent_due_at > child_unlock_at\n      raise PeerReview::InvalidDatesError,\n            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\")\n    elsif !parent_due_at && parent_unlock_at && child_unlock_at && parent_unlock_at > child_unlock_at\n      raise PeerReview::InvalidDatesError,\n            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\")\n    end\n\n    # Validate: parent unlock_at <= child due_at (for backward compatibility)\n    if parent_unlock_at && child_due_at && parent_unlock_at > child_due_at\n      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?","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/peer_review/validations.rb#L159-L195","documentation":"PeerReview::InvalidDatesError from the parent due_at <= child due_at check (line 176-178) in validate_dates_within_parent_boundaries: peer reviews must be due no earlier than the parent assignment/override due date. For overrides the message is 'Peer review override due date cannot be before parent override due date'; the non-override variant is 'Peer review due date cannot be before assignment due date'. This enforces the documented chain assignment due <= peer review due.","triggerScenarios":"Calling validate_override_dates_against_parent_override where the parent override's due_at_overridden timestamp is later than the peer review override's due_at, or validate_peer_review_dates_against_parent_assignment where assignment.due_at > peer review due_at.","commonSituations":"Teacher extends the assignment due date after peer review dates were configured; API clients computing peer review due as 'assignment due minus N days' for staggered workflows (unsupported ordering); timezone shifts making the parent due appear later.","solutions":["Raise the peer review due_at to a timestamp >= parent (override) due_at","Or move the parent due_at earlier so the intended peer review ordering is valid","If the workflow needs reviews before the assignment due date, note this ordering is not allowed — redesign dates to parent due <= review due","Pre-validate: raise if parent.due_at && child.due_at && parent.due_at > child.due_at"],"exampleFix":"// before\nparent_due = '2026-05-10T00:00:00Z'; peer_review_due = '2026-05-05T00:00:00Z'\n// after\nparent_due = '2026-05-10T00:00:00Z'; peer_review_due = '2026-05-12T00:00:00Z'","handlingStrategy":"validation","validationCode":"def review_due_not_before_parent_due?(parent, pr_dates)\n  return true if parent.due_at.nil? || pr_dates[:due_at].nil?\n  parent.due_at <= Time.zone.parse(pr_dates[:due_at].to_s)\nend","typeGuard":null,"tryCatchPattern":"begin\n  validator.validate_override_dates_against_parent_override(pr_override, parent_override)\nrescue PeerReview::InvalidDatesError => e\n  if e.message.include?('cannot be before parent override due date') || e.message.include?('before assignment due date')\n    pr_override.due_at = parent.due_at + 1.day\n    retry\n  end\n  raise\nend","preventionTips":["Re-run peer review validation whenever the parent due date is extended","Model review deadlines as offsets from the parent due (due_at + N days), not absolutes","Add a regression test covering parent-due-extended-after-review-configured","Document to teachers that reviews cannot close before the assignment is due"],"tags":["peer-review","date-validation","parent-assignment","canvas-lms"],"backgroundTag":"invalid-argument-value","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"}