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

Invalid parent assignment

Error message

Invalid parent assignment

What it means

PeerReview::Validations#validate_parent_assignment raises PeerReview::InvalidParentAssignmentError when the assignment passed to a peer-review service is nil, not an Assignment instance, or not persisted to the database. Peer review sub-assignments must be attached to a real, saved parent assignment, so the library refuses to operate on unsaved or wrong-typed objects.

Solutions

  1. Save the assignment first and check `assignment.persisted?` before invoking peer review services.
  2. Verify you are passing the parent Assignment object, not nil or another model.
  3. In specs/tests, use a persisted factory-created assignment (create(:assignment)) rather than build(:assignment).

Example fix

// before
sub_assignment = PeerReview::CreatorService.new(parent_assignment: assignment)
# assignment was built but never saved
// after
assignment.save!
raise "parent must be persisted" unless assignment.persisted?
sub_assignment = PeerReview::CreatorService.new(parent_assignment: assignment)
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, "parent assignment must be persisted" unless assignment.is_a?(Assignment) && assignment.persisted?

Type guard

def valid_parent_assignment?(a) = a.is_a?(Assignment) && a.persisted?

Try / catch

begin
  service.call
rescue PeerReview::InvalidParentAssignmentError => e
  Rails.logger.warn("peer review: #{e.message}")
  render json: { error: e.message }, status: :unprocessable_entity
end

Prevention

When it happens

Trigger: Calling any peer review service that includes PeerReview::Validations with assignment = nil; passing a non-Assignment object (e.g. a sub-assignment or an Assignment clone); passing an Assignment built with Assignment.new but never saved (not persisted).

Common situations: Building an assignment in a controller and calling peer-review creation before `save` succeeds; refactoring code that now passes an Assignment object from a different namespace or a test double; a failed save returning an unsaved model that is then handed to the service.

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

Appendix: source

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

#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

module PeerReview::Validations
  def validate_parent_assignment(assignment)
    unless assignment.present? && assignment.is_a?(Assignment) && assignment.persisted?
      raise PeerReview::InvalidParentAssignmentError, I18n.t("Invalid parent assignment")
    end
  end

  def validate_peer_reviews_enabled(assignment)
    unless assignment.peer_reviews?
      raise PeerReview::PeerReviewsNotEnabledError, I18n.t("Peer reviews are not enabled for this assignment")
    end
  end

  def validate_feature_enabled(assignment)
    unless assignment.context.feature_enabled?(:peer_review_allocation_and_grading)
      raise PeerReview::FeatureDisabledError, I18n.t("Peer Review Allocation and Grading feature flag is disabled")
    end
  end

  def validate_grading_type(grading_type)
    raise PeerReview::InvalidGradingTypeError, I18n.t("Peer review sub assignments cannot have a not_graded grading type") if grading_type == "not_graded"
  end

View on GitHub (pinned to 1c9f0bb801)