{"record":{"id":"0cad7e76c03e7d2f","repo":"instructure/canvas-lms","slug":"invalid-parent-assignment","errorCode":null,"errorMessage":"Invalid parent assignment","messagePattern":"Invalid parent assignment","errorType":"validation","errorClass":"PeerReview::InvalidParentAssignmentError","httpStatus":null,"severity":"error","filePath":"app/services/peer_review/validations.rb","lineNumber":23,"sourceCode":"#\n# This file is part of Canvas.\n#\n# Canvas is free software: you can redistribute it and/or modify it under\n# the terms of the GNU Affero General Public License as published by the Free\n# Software Foundation, version 3 of the License.\n#\n# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\n# details.\n#\n# You should have received a copy of the GNU Affero General Public License along\n# with this program. If not, see <http://www.gnu.org/licenses/>.\n\nmodule PeerReview::Validations\n  def validate_parent_assignment(assignment)\n    unless assignment.present? && assignment.is_a?(Assignment) && assignment.persisted?\n      raise PeerReview::InvalidParentAssignmentError, I18n.t(\"Invalid parent assignment\")\n    end\n  end\n\n  def validate_peer_reviews_enabled(assignment)\n    unless assignment.peer_reviews?\n      raise PeerReview::PeerReviewsNotEnabledError, I18n.t(\"Peer reviews are not enabled for this assignment\")\n    end\n  end\n\n  def validate_feature_enabled(assignment)\n    unless assignment.context.feature_enabled?(:peer_review_allocation_and_grading)\n      raise PeerReview::FeatureDisabledError, I18n.t(\"Peer Review Allocation and Grading feature flag is disabled\")\n    end\n  end\n\n  def validate_grading_type(grading_type)\n    raise PeerReview::InvalidGradingTypeError, I18n.t(\"Peer review sub assignments cannot have a not_graded grading type\") if grading_type == \"not_graded\"\n  end","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/peer_review/validations.rb#L5-L41","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Save the assignment first and check `assignment.persisted?` before invoking peer review services.","Verify you are passing the parent Assignment object, not nil or another model.","In specs/tests, use a persisted factory-created assignment (create(:assignment)) rather than build(:assignment)."],"exampleFix":"// before\nsub_assignment = PeerReview::CreatorService.new(parent_assignment: assignment)\n# assignment was built but never saved\n// after\nassignment.save!\nraise \"parent must be persisted\" unless assignment.persisted?\nsub_assignment = PeerReview::CreatorService.new(parent_assignment: assignment)","handlingStrategy":"validation","validationCode":"raise ArgumentError, \"parent assignment must be persisted\" unless assignment.is_a?(Assignment) && assignment.persisted?","typeGuard":"def valid_parent_assignment?(a) = a.is_a?(Assignment) && a.persisted?","tryCatchPattern":"begin\n  service.call\nrescue PeerReview::InvalidParentAssignmentError => e\n  Rails.logger.warn(\"peer review: #{e.message}\")\n  render json: { error: e.message }, status: :unprocessable_entity\nend","preventionTips":["Always save! the parent assignment before peer review operations","Use create/factory-created records in tests, not build","Never pass nil; fetch with find! so missing records fail early"],"tags":["peer-review","rails","validation","activerecord"],"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"}