instructure/canvas-lms · error · GraphQL::ExecutionError
Only one assessor is allowed when creating reciprocal rules
Error message
Only one assessor is allowed when creating reciprocal rules
What it means
Raised by validate_id_arrays! in AllocationRuleBase when the mutation input has reciprocal: true but the assessor_ids array contains more than one ID. Reciprocal allocation rules pair exactly one assessor with exactly one assessee, so multiple assessors are rejected. The error surfaces as a GraphQL ExecutionError on the mutation result.
Solutions
- Send only one assessor ID when reciprocal: true.
- Split multiple pairs into separate mutation calls (one per reciprocal pair).
- Omit reciprocal: true if multiple assessors are actually intended.
- Add client-side validation limiting assessorIds to length 1 when the reciprocal checkbox is on.
Example fix
// before
{ reciprocal: true, assessorIds: ["11", "12"], assesseeIds: ["21"] }
// after (one pair per call)
{ reciprocal: true, assessorIds: ["11"], assesseeIds: ["21"] }
{ reciprocal: true, assessorIds: ["12"], assesseeIds: ["21"] } Defensive patterns
Strategy: validation
Validate before calling
if (input.reciprocal && input.assessorIds.length > 1) {
throw new Error('Reciprocal rules require exactly one assessor');
} Try / catch
try {
await createAllocationRules(input);
} catch (e) {
if (e.message.includes('Only one assessor is allowed when creating reciprocal rules')) {
// fall back to per-pair mutation calls
}
} Prevention
- Cap assessor selection to 1 in the UI when reciprocal is checked
- Create reciprocal rules one pair per mutation call
- Do not reuse bulk payloads across rule modes
- Unit-test input builders per rule mode
When it happens
Trigger: Calling an allocation-rule create mutation with input { reciprocal: true, assessorIds: [id1, id2, ...], assesseeIds: [x] } — i.e. reciprocal flag set with assessor_ids.length > 1.
Common situations: A frontend batch-creates reciprocal rules in one call instead of one call per pair; copying a bulk-assessor payload from a non-reciprocal flow and adding reciprocal: true; misunderstanding that reciprocal means pair-wise and must be created one pair at a time.
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
- Only one assessee is allowed when creating reciprocal rules
- A maximum of 50 assessees can be provided at once
- A maximum of 50 assessors can be provided at once
- At least one assessee is required
- At least one assessor is required
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/0ada1ddb5ea976d8.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/allocation_rule_base.rb:86
field :allocation_rules, [Types::AllocationRuleType], null: true
protected
def validate_feature_flag!(course)
unless course.feature_enabled?(:peer_review_allocation_and_grading)
raise GraphQL::ExecutionError, I18n.t("peer_review_allocation_and_grading feature flag is not enabled for this course")
end
end
def validate_id_arrays!(input)
assessor_ids = input[:assessor_ids]
assessee_ids = input[:assessee_ids]
applies_to_assessor = input[:applies_to_assessor]
reciprocal = input[:reciprocal]
if reciprocal
if assessor_ids.length > 1
raise GraphQL::ExecutionError, I18n.t("Only one assessor is allowed when creating reciprocal rules")
end
if assessee_ids.length > 1
raise GraphQL::ExecutionError, I18n.t("Only one assessee is allowed when creating reciprocal rules")
end
elsif applies_to_assessor
if assessor_ids.length > 1
raise GraphQL::ExecutionError, I18n.t("Only one assessor is allowed when rule applies to assessor")
end
elsif assessee_ids.length > 1
raise GraphQL::ExecutionError, I18n.t("Only one assessee is allowed when rule applies to assessee")
end
if assessor_ids.empty?
raise GraphQL::ExecutionError, I18n.t("At least one assessor is required")
end
if assessee_ids.empty?
raise GraphQL::ExecutionError, I18n.t("At least one assessee is required")
endView on GitHub (pinned to 1c9f0bb801)