instructure/canvas-lms · error · RuntimeError
Assessor required for assessing
Error message
Assessor required for assessing
What it means
RubricAssociation#assess requires the caller to supply a hash of options including :user, :assessor, :artifact, and the assessment params. This guard fires when opts[:assessor] is nil/absent, meaning Canvas cannot record who performed the rubric assessment. It is a fail-fast contract check before any assessment rows are created.
Solutions
- Pass opts[:assessor] with the User (or user object) performing the assessment: ra.assess(user: student, assessor: teacher, artifact: submission, assessment: {assessment_type: 'grading'})
- Verify the assessor is resolved before calling assess (e.g. assessor = User.find(teacher_id); raise early with a friendlier message if nil)
- If integrating via the Submissions/Assessments API, confirm the endpoint supplies the assessor (the current user) rather than only the student
Example fix
// before
rubric_association.assess(
user: student,
artifact: submission,
assessment: { assessment_type: 'grading', ... }
)
// after
rubric_association.assess(
user: student,
assessor: current_user,
artifact: submission,
assessment: { assessment_type: 'grading', ... }
) Defensive patterns
Strategy: validation
Validate before calling
raise 'assessor required' unless opts[:assessor] rubric_association.assess(user:, assessor:, artifact:, assessment:)
Type guard
valid = opts[:assessor].is_a?(User)
Try / catch
begin rubric_association.assess(opts) rescue RuntimeError => e handle_missing_assessor if e.message == 'Assessor required for assessing' end
Prevention
- Always pass the performing teacher/user as :assessor
- Build assess params via a shared helper that asserts all required keys
- Add request specs covering rubric assessment creation
When it happens
Trigger: Calling rubric_association.assess(user:, artifact:, assessment: {...}) without opts[:assessor]; callers building the assess params hash programmatically (e.g. from an API request or LTI tool) and omitting the assessor id; assessor object resolved to nil because the supplied user id does not map to a real user with grading rights.
Common situations: Custom integrations or scripts that call assess directly and copy the wrong param key (e.g. :assessor_id instead of :assessor); third-party rubric tools passing incomplete params; refactors that removed the assessor lookup but left the assess call in place.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Artifact required for assessing
- Assessment type required for assessing
- assessor and assessee required
- association required
- Cannot find # for ID: #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/c761143bd2326bd4.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/rubric_association.rb:309
end
def assessment_points(criterion, data)
if criterion.learning_outcome_id && !context.feature_enabled?(:outcome_extra_credit)
[criterion.points, data[:points].to_f].min
else
data[:points].to_f
end
end
protected :assessment_points
def assess(opts = {})
# TODO: what if this is for a group assignment? Seems like it should
# give all students for the group assignment the same rubric assessment
# results.
association = self
params = opts[:assessment]
raise "User required for assessing" unless opts[:user]
raise "Assessor required for assessing" unless opts[:assessor]
raise "Artifact required for assessing" unless opts[:artifact]
raise "Assessment type required for assessing" unless params[:assessment_type]
if opts[:artifact].is_a?(Quizzes::QuizSubmission)
opts[:artifact] = association_object.find_or_create_submission(opts[:artifact].user)
end
if association_object.is_a?(Assignment) && !association_object.grade_group_students_individually
group, students_to_assess = association_object.group_students(opts[:artifact].student)
if group
provisional_grader = opts[:artifact].is_a?(ModeratedGrading::ProvisionalGrade) && opts[:assessor]
artifacts_to_assess = students_to_assess.map do |student|
association_object.find_asset_for_assessment(self, student, provisional_grader:).first
end
else
artifacts_to_assess = [opts[:artifact]]
end
elseView on GitHub (pinned to 1c9f0bb801)