{"record":{"id":"78d1fd56e31ae5ea","repo":"instructure/canvas-lms","slug":"no-type-given-for-change-sis-id","errorCode":null,"errorMessage":"No type given for change_sis_id","messagePattern":"No type given for change_sis_id","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/change_sis_id_importer.rb","lineNumber":68,"sourceCode":"      scope.update_all(sis_batch_id: @batch.id, updated_at: Time.now.utc)\n    end\n\n    class Work\n      attr_accessor :success_count,\n                    :things_to_update_batch_ids,\n                    :users_to_sync\n\n      def initialize(batch, root_account, logger)\n        @batch = batch\n        @root_account = root_account\n        @logger = logger\n        @success_count = 0\n        @things_to_update_batch_ids = {}\n        @users_to_sync = Set.new\n      end\n\n      def process_change_sis_id(data_change)\n        raise ImportError, \"No type given for change_sis_id\" if data_change.type.blank?\n        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?\n        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?\n\n        type = data_change.type.downcase.strip\n        things_to_update_batch_ids[type] ||= Set.new\n\n        types = {\n          \"user\" => { scope: @root_account.pseudonyms, column: :sis_user_id },\n          \"course\" => { scope: @root_account.all_courses },\n          \"section\" => { scope: @root_account.course_sections },\n          \"term\" => { scope: @root_account.enrollment_terms },\n          \"account\" => { scope: @root_account.all_accounts },\n          \"group\" => { scope: @root_account.all_groups },\n          \"group_category\" => { scope: @root_account.all_group_categories },\n        }\n\n        details = types[type]\n        raise ImportError, \"Invalid type '#{type}' for change_sis_id\" unless details","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/change_sis_id_importer.rb#L50-L86","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Populate the type column with one of: user, course, section, term, account, group, group_category.","Fix the CSV header so the parser maps the correct column into data_change.type.","Filter out blank/short rows before yielding to process_change_sis_id."],"exampleFix":"// before\ntype,,old_id,U1,new_id,U2\n// after\ntype,old_id,new_id\nuser,U1,U2","handlingStrategy":"validation","validationCode":"raise ArgumentError, 'type required' if data_change.type.blank?\nprocess_change_sis_id(data_change)","typeGuard":"def valid_type?(dc)\n  %w[user course section term account group group_category].include?(dc.type.to_s.downcase.strip)\nend","tryCatchPattern":"begin\n  process_change_sis_id(dc)\nrescue SIS::ImportError => e\n  logger.warn(\"skipped row: #{e.message}\")\n  errors << e.message\nend","preventionTips":["Validate CSV headers against the documented change_sis_id schema before import.","Skip or reject blank/short rows at parse time.","Unit-test your CSV generator with a row-level schema check."],"tags":["sis","ruby","import","validation","csv"],"backgroundTag":"missing-required-argument","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}