instructure/canvas-lms · error · ImportError

No type given for change_sis_id

Error message

No type given for change_sis_id

What it means

SIS::ChangeSisIdImporter::Work#process_change_sis_id raises this ImportError when the SIS change-sis-id row has a blank `type`. The type selects which AR scope/column mapping (user, course, section, term, account, group, group_category) to use, so without it no lookup can even be attempted. It is a hard fail-fast guard at the top of the method.

Solutions

  1. Populate the type column with one of: user, course, section, term, account, group, group_category.
  2. Fix the CSV header so the parser maps the correct column into data_change.type.
  3. Filter out blank/short rows before yielding to process_change_sis_id.

Example fix

// before
type,,old_id,U1,new_id,U2
// after
type,old_id,new_id
user,U1,U2
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, 'type required' if data_change.type.blank?
process_change_sis_id(data_change)

Type guard

def valid_type?(dc)
  %w[user course section term account group group_category].include?(dc.type.to_s.downcase.strip)
end

Try / catch

begin
  process_change_sis_id(dc)
rescue SIS::ImportError => e
  logger.warn("skipped row: #{e.message}")
  errors << e.message
end

Prevention

When it happens

Trigger: A change_sis_id CSV/attr row (e.g. SIS CSV 'change_sis_id' file or batch data_change) where the type column is empty/whitespace: data_change.type is nil or ''. Raised before any DB lookup.

Common situations: CSV rows with a missing or misnamed 'type' column (header typo like 'object_type'), rows generated by external scripts that omit type, or trailing blank lines parsed as data rows.

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/78d1fd56e31ae5ea. Report an issue: GitHub.

Appendix: source

Thrown at lib/sis/change_sis_id_importer.rb:68

      scope.update_all(sis_batch_id: @batch.id, updated_at: Time.now.utc)
    end

    class Work
      attr_accessor :success_count,
                    :things_to_update_batch_ids,
                    :users_to_sync

      def initialize(batch, root_account, logger)
        @batch = batch
        @root_account = root_account
        @logger = logger
        @success_count = 0
        @things_to_update_batch_ids = {}
        @users_to_sync = Set.new
      end

      def process_change_sis_id(data_change)
        raise ImportError, "No type given for change_sis_id" if data_change.type.blank?
        raise ImportError, "No old_id or old_integration_id given for change_sis_id" if data_change.old_id.blank? && data_change.old_integration_id.blank?
        raise ImportError, "No new_id or new_integration_id given for change_sis_id" if data_change.new_id.blank? && data_change.new_integration_id.blank?

        type = data_change.type.downcase.strip
        things_to_update_batch_ids[type] ||= Set.new

        types = {
          "user" => { scope: @root_account.pseudonyms, column: :sis_user_id },
          "course" => { scope: @root_account.all_courses },
          "section" => { scope: @root_account.course_sections },
          "term" => { scope: @root_account.enrollment_terms },
          "account" => { scope: @root_account.all_accounts },
          "group" => { scope: @root_account.all_groups },
          "group_category" => { scope: @root_account.all_group_categories },
        }

        details = types[type]
        raise ImportError, "Invalid type '#{type}' for change_sis_id" unless details

View on GitHub (pinned to 1c9f0bb801)