instructure/canvas-lms · error · ImportError

Improper status "# " for an enrollment

Error message

Improper status "#{enrollment.status}" for an enrollment

What it means

EnrollmentImporter.add_enrollment raises ImportError when `enrollment.valid_status?` is false, i.e. the enrollment status is not one of the accepted values (active, deleted, completed, inactive and variants, case-insensitive). The interpolated status is included in the message to show the offending value.

Solutions

  1. Map source statuses to Canvas-accepted values: active, deleted, completed, inactive (case-insensitive)
  2. Trim/normalize the status string before constructing the Enrollment
  3. Add a preprocessing step that translates foreign status vocabularies
  4. Check the CSV header mapping so the status column is parsed correctly

Example fix

// before
SIS::Models::Enrollment.new(course_id: 'c1', user_id: 'u1', status: 'enrolled')
// after
SIS::Models::Enrollment.new(course_id: 'c1', user_id: 'u1', status: 'active')
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = %w[active deleted completed inactive]
raise 'bad status' unless ALLOWED.include?(enrollment.status.to_s.strip.downcase)

Try / catch

begin
  importer.add_enrollment(enrollment)
rescue SIS::Base::ImportError => e
  logger.warn("Skipping enrollment: #{e.message}")
end

Prevention

When it happens

Trigger: Calling `add_enrollment(enrollment)` with a status like 'enrolled', 'ACTIVE ', 'drop', or a typo such as 'actve'; CSV rows with unexpected values in the status/enrollment_state column.

Common situations: Exports from other SIS/LMS systems using their own state vocabularies ('enrolled', 'pending', 'withdrawn'); trailing whitespace or casing assumptions; header mapped to the wrong column (e.g. role instead of status).

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/4a73df0f3f297b53. Report an issue: GitHub.

Appendix: source

Thrown at lib/sis/enrollment_importer.rb:135

        @courses_to_touch_ids = Set.new
        @courses_to_recache_due_dates = {}
        @enrollments_to_add_to_favorites = []
        @enrollments_to_update_sis_batch_ids = []
        @roll_back_data = []
        @enrollments_to_delete = []
        @account_chain_cache = {}
        @course = @section = nil
        @course_roles_by_account_id = {}

        @enrollment_batch = []
        @success_count = 0
      end

      # Pass a single instance of SIS::Models::Enrollment
      def add_enrollment(enrollment)
        raise ImportError, "No course_id or section_id given for an enrollment" unless enrollment.valid_context?
        raise ImportError, "No user_id given for an enrollment" unless enrollment.valid_user?
        raise ImportError, "Improper status \"#{enrollment.status}\" for an enrollment" unless enrollment.valid_status?
        return if @batch.skip_deletes? && enrollment.status =~ /deleted/i

        @enrollment_batch << enrollment
        process_batch if @enrollment_batch.size >= BATCH_SIZE
      end

      def any_left_to_process?
        !@enrollment_batch.empty?
      end

      def process_batch
        return unless any_left_to_process?

        enrollment_info = nil
        until @enrollment_batch.empty?
          enrollment_info = @enrollment_batch.shift

          @last_section = @section if @section

View on GitHub (pinned to 1c9f0bb801)