instructure/canvas-lms · error · ImportError

No user_id given for an enrollment

Error message

No user_id given for an enrollment

What it means

Validation guard raised by SisImports::Errors when add_enrollment is called with a blank user_id on the SIS::Models::Enrollment row. It fires during SIS enrollment CSV ingestion before any database lookup, aborting the batch (or row batch) because an enrollment cannot be attached to a user without an identifier.

Solutions

  1. Ensure each enrollments CSV row includes a valid user_id (SIS user id)
  2. Fix column headers/mapping so user_id is parsed into the model
  3. For programmatic use, pass `user_id:` when constructing the Enrollment

Example fix

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

Strategy: validation

Validate before calling

raise 'missing user_id' if enrollment.user_id.blank?

Type guard

def has_user?(enrollment)
  enrollment.user_id.present?
end

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 an Enrollment whose user_id is nil/blank; an enrollments CSV row missing the user_id column; a user_id referencing a user that produced no lookup value during parsing.

Common situations: CSV exported with a different user column name (e.g. login instead of user_id); rows for users deleted from the source system; scripts building Enrollment objects without setting user_id.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at lib/sis/enrollment_importer.rb:134

        @users_to_touch_ids = Set.new
        @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

View on GitHub (pinned to 1c9f0bb801)