instructure/canvas-lms · error · GraphQL::ExecutionError
Course not found
Error message
Course not found
What it means
create_comment_bank_item#get_course uses Course.active.find_by(id: course_id) and raises 'Course not found' when nil. Because it uses the active scope, deleted or concluded courses are treated as missing even if the row exists.
Solutions
- Verify Course.active.find_by(id: course_id) returns a record in rails console
- Pass a valid legacy numeric course id in the correct shard
- Re-fetch course ids from the API if the course may have been deleted
- Ensure the user's GraphQL context resolves the course's root account
Example fix
// before get_course(nil) // course_id not resolved from context_code // after course = Course.active.find_by(id: parsed_course_id) raise GraphQL::ExecutionError, "Course not found" unless course
Defensive patterns
Strategy: validation
Validate before calling
let course
try { course = await canvas.get(`/api/v1/courses/${courseId}`) } catch { course = null }
if (!course || course.workflow_state !== 'available') throw new Error('Course not found or not active') Type guard
function isActiveCourse(c) { return c != null && c.id != null && c.workflow_state === 'available' } Try / catch
try {
await client.mutate({ mutation: CREATE_COMMENT_BANK_ITEM, variables: { courseId } })
} catch (e) {
if (e.message.includes('Course not found')) {
// re-resolve courseId from the context code before retrying
}
throw e
} Prevention
- Derive courseId from a live context code each session, not cached values
- Confirm the course is in 'available' (active) workflow state
- Validate id formats before sending GraphQL variables
- Check shard/root-account context resolves the course
When it happens
Trigger: Calling createCommentBankItem with a courseId that is nil, deleted/concluded, nonexistent, or from a different shard/root account context.
Common situations: Client passes context code-derived id from a course since deleted; id format mismatch (relay id vs legacy id); course on another shard not resolved in the GraphQL context.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- A course with that id does not exist
- Assignment not found
- Assignment not found
- custom grade status not found
- invalid course: #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/0f1e57a135cc0da8.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/create_comment_bank_item.rb:43
argument :comment, String, required: true
argument :course_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("Course")
field :comment_bank_item, Types::CommentBankItemType, null: true
def resolve(input:)
course = get_course(input[:course_id])
assignment = get_assignment(input[:assignment_id], course) if input[:assignment_id]
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)