instructure/canvas-lms · error · RequestError

Invalid enrollment type: #

Error message

Invalid enrollment type: #{e}

What it means

UserSearch.validate_enrollment_types in lib/user_search.rb:26 raises RequestError (400) when a camelized enrollment type is not a key in Enrollment.readable_types. It guarantees the enrollment_types filter passed to user queries only contains enrollment types the searcher is permitted to read.

Solutions

  1. Use valid enrollment type strings: TeacherEnrollment, StudentEnrollment, TaEnrollment, DesignerEnrollment, ObserverEnrollment
  2. Validate/whitelist enrollment_type params in the controller before calling UserSearch
  3. Check Enrollment.readable_types in a console to list valid types for the context
  4. Rescue RequestError to convert it into a 400 response with a clear message

Example fix

// before
UserSearch.validate_enrollment_types(['Student'])
// after
UserSearch.validate_enrollment_types(['StudentEnrollment']) # or 'student', which camelizes correctly
Defensive patterns

Strategy: validation

Validate before calling

invalid = enrollment_types.reject { |e| Enrollment.readable_types.key?(e.camelize.sub(/Enrollment\z/, '') == e.camelize ? e.camelize : e.camelize + 'Enrollment') }

Try / catch

begin
  UserSearch.validate_enrollment_types(params[:enrollment_type])
rescue RequestError => e
  render json: {error: e.message}, status: 400
end

Prevention

When it happens

Trigger: Passing enrollment_types like ['StudentEnrollment'] misspelled, or types such as 'FakeEnrollment', or values not readable in the context into UserSearch / roles_scope.

Common situations: API params enrollment_type[] with invalid values hitting user index endpoints; plugins or custom code referencing removed enrollment types; typos like 'TaEnrollment' vs 'TaEnrolment' in client code.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at lib/user_search.rb:26

# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

module UserSearch
  class << self
    def validate_enrollment_types(enrollment_types)
      enrollment_types.map do |e|
        ce = e.camelize
        ce += "Enrollment" unless ce.end_with?("Enrollment")
        raise RequestError.new("Invalid enrollment type: #{e}", 400) unless Enrollment.readable_types.key?(ce)

        ce
      end
    end

    def for_user_in_context(search_term, context, searcher, session = nil, options = {})
      search_term = search_term.to_s
      return User.none if search_term.strip.empty?

      SearchTermHelper.validate_search_term(search_term)

      @is_id = search_term =~ Api::ID_REGEX && Api::MAX_ID_RANGE.cover?(search_term.to_i)
      @include_login       = context.grants_right?(searcher, session, :view_user_logins)
      @include_email       = context.grants_right?(searcher, session, :read_email_addresses)
      @include_sis         = context.grants_any_right?(searcher, session, :read_sis, :manage_sis)
      @include_integration = @include_sis
      @include_deleted_users = options[:include_deleted_users]

View on GitHub (pinned to 1c9f0bb801)