instructure/canvas-lms · error · GraphQL::ExecutionError

not found

Error message

not found

What it means

CreateModule#resolve rescues ActiveRecord::RecordNotFound and converts it to GraphQL::ExecutionError 'not found'. The mutation looks up its context (e.g. course from course_id) with find(), so an unknown or inaccessible context ID raises RecordNotFound before any module is created.

Solutions

  1. Verify the courseId exists and is visible to the current user via a GraphQL course query first.
  2. Use a Node/context lookup to confirm the ID resolves on the current shard.
  3. If authorization is the real issue, call as a user enrolled in the course (errors are masked as not-found by design).
  4. Handle 'not found' errors in the client and prompt the user to re-select the course.

Example fix

// before
const res = await gql(createModuleMutation, { input: { courseId: hardcodedId } })
// after
const course = await gql(getCourseQuery, { id: hardcodedId })
if (!course?.id) throw new Error('Course not accessible')
const res = await gql(createModuleMutation, { input: { courseId: hardcodedId } })
Defensive patterns

Strategy: validation

Validate before calling

const course = await gql(GET_COURSE, { id: courseId })
if (!course) throw new Error(`course ${courseId} not found or not visible`)

Type guard

function isResolvableCourse(c) { return c != null && typeof c._id === 'string' }

Try / catch

try {
  await gql(CREATE_MODULE, { input })
} catch (e) {
  if (e.message === 'not found') await promptCourseReselection()
  else throw e
}

Prevention

When it happens

Trigger: Calling createModule with a courseId that doesn't exist, belongs to another root account/shard, or that the loader refuses to resolve for an unauthorized user (Canvas loaders raise RecordNotFound for hidden records).

Common situations: Hardcoded course IDs copied between environments; IDs from a deleted course; querying from a token whose user cannot see the course (loaders return not-found instead of forbidden).

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


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/475c0a19920b219a. Report an issue: GitHub.

Appendix: source

Thrown at app/graphql/mutations/create_module.rb:44

  field :module, Types::ModuleType, null: true, resolver_method: :will_not_be_called
  def will_not_be_called
    # This is a silly workaround for https://github.com/rmosolgo/graphql-ruby/issues/2723
  end

  def resolve(input:)
    course_id = GraphQLHelpers.parse_relay_or_legacy_id(input[:course_id], "Course")
    course = Course.find(course_id)
    verify_authorized_action!(course.context_modules.temp_record, :create)
    mod = course.context_modules.build(name: input[:name])
    mod.require_presence_of_name = true
    if mod.save
      { module: mod }
    else
      errors_for(mod)
    end
  rescue ActiveRecord::RecordNotFound
    raise GraphQL::ExecutionError, "not found"
  end
end

View on GitHub (pinned to 1c9f0bb801)