instructure/canvas-lms · error · GraphQL::ExecutionError
Assignment not found
Error message
Assignment not found
What it means
create_comment_bank_item#get_assignment looks up the assignment via AbstractAssignment.assignment_scope_for_context(course).active.find(assignment_id); ActiveRecord::RecordNotFound is rescued and re-raised as 'Assignment not found'. The scope restricts to assignments visible in that course context, so mismatched course/assignment pairs also fail.
Solutions
- Confirm the assignment belongs to the same course passed as courseId and is active
- Check the id is in the scope: AbstractAssignment.assignment_scope_for_context(course).active.find(id) in console
- Use fresh assignment ids from the course's assignments query rather than cached values
- Verify shard/id format (legacy numeric vs relay id)
Example fix
// before
createCommentBankItem(input: { courseId: "1", assignmentId: "999" }) // assignment in course 2
// after
assignment = course.assignments.active.first
createCommentBankItem(input: { courseId: "1", assignmentId: assignment.id.to_s }) Defensive patterns
Strategy: validation
Validate before calling
const assignments = await canvas.get(`/api/v1/courses/${courseId}/assignments`)
if (!assignments.some(a => String(a.id) === String(assignmentId))) throw new Error('assignment not in this course or inactive') Type guard
function belongsToCourse(a, courseId) { return a != null && a.course_id != null && String(a.course_id) === String(courseId) && !a.deleted_at } Try / catch
try {
await client.mutate({ mutation: CREATE_COMMENT_BANK_ITEM, variables: { courseId, assignmentId } })
} catch (e) {
if (e.message.includes('Assignment not found')) {
// verify course/assignment pairing, then refetch ids
}
throw e
} Prevention
- Only pair assignment ids with the course they belong to
- Refetch assignments rather than caching ids across terms
- Exclude assignment types filtered by the context scope (quizzes/LTI) where relevant
- Normalize both ids to the same format before calling
When it happens
Trigger: Calling createCommentBankItem with an assignmentId that doesn't belong to the given course, is deleted, is not in the context's assignment scope (e.g. subassignment/quiz type excluded), or a nonexistent id.
Common situations: Assignment id taken from a different course than the courseId supplied; assignment soft-deleted; wiki/LTI assignment types filtered out by assignment_scope_for_context; cross-shard id.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Assignment not found
- An assignment with that id does not exist
- Course not found
- custom grade status not found
- not found
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/75e742a19aca1b75.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/create_comment_bank_item.rb:50
record = CommentBankItem.new(course:, user: current_user, comment: input[:comment], assignment:)
verify_authorized_action!(record, :create)
return errors_for(record) unless record.save
{ comment_bank_item: record }
end
private
def get_course(course_id)
Course.active.find_by(id: course_id).tap do |course|
raise GraphQL::ExecutionError, I18n.t("Course not found") if course.nil?
end
end
def get_assignment(assignment_id, course)
AbstractAssignment.assignment_scope_for_context(course).active.find(assignment_id)
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, I18n.t("Assignment not found")
end
end
View on GitHub (pinned to 1c9f0bb801)