{"record":{"id":"9e772aef753db845","repo":"instructure/canvas-lms","slug":"invalid-type-type-for-change-sis-id","errorCode":null,"errorMessage":"Invalid type '#{type}' for change_sis_id","messagePattern":"Invalid type '#(.+?)' for change_sis_id","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/change_sis_id_importer.rb","lineNumber":86,"sourceCode":"        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\n\n        column = details[:column] || :sis_source_id\n        check_for_conflicting_ids(column, details, type, data_change)\n        old_item = find_item_to_update(column, details, type, data_change)\n        update_record(column, data_change, details, old_item)\n        things_to_update_batch_ids[type] << old_item.id\n        users_to_sync << old_item.user_id if type == \"user\"\n        self.success_count += 1\n      end\n\n      def update_record(column, data_change, details, old_item)\n        updates = ids_to_change(column, data_change)\n        details[:scope].where(id: old_item.id).update_all(updates)\n        old_item.invalidate_association_cache if old_item.is_a?(Account)\n        # update_all bypasses AR callbacks; re-index GlobalLookups\n        # so cross-shard searches can find the new IDs.\n        if old_item.is_a?(Pseudonym) && GlobalLookups.enabled?\n          old_item.delay_if_production.ensure_global_lookup_record(force: true)","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/change_sis_id_importer.rb#L68-L104","documentation":"After downcasing/stripping the type, process_change_sis_id looks it up in a fixed hash of seven supported types (user, course, section, term, account, group, group_category). Any other value raises this ImportError because there is no scope/column mapping for it.","triggerScenarios":"type values like 'enrollment', 'assignment', 'User ' variants that map to nothing after downcase/strip (e.g. 'pseudonym', 'users', 'group_category ' misspelled as 'groupcategory'), or singular/plural mismatches.","commonSituations":"Assuming any Canvas object type is changeable; typos in hand-written CSVs; integrations emitting their own internal type names instead of Canvas's change_sis_id type vocabulary.","solutions":["Use exactly one of: user, course, section, term, account, group, group_category (case/whitespace is normalized).","To change a user's SIS login id note 'user' maps to Pseudonyms with column sis_user_id.","Reject unsupported types at CSV-generation time in the upstream system."],"exampleFix":"// before\ntype,old_id,new_id\nenrollment,E1,E2\n// after\ntype,old_id,new_id\ncourse,C1,C2","handlingStrategy":"validation","validationCode":"VALID_TYPES = %w[user course section term account group group_category]\nunless VALID_TYPES.include?(dc.type.to_s.downcase.strip)\n  raise ArgumentError, \"unsupported type: #{dc.type}\"\nend\nprocess_change_sis_id(dc)","typeGuard":"VALID_TYPES = %w[user course section term account group group_category].freeze\ndef supported_type?(dc)\n  VALID_TYPES.include?(dc.type.to_s.downcase.strip)\nend","tryCatchPattern":"begin\n  process_change_sis_id(dc)\nrescue SIS::ImportError => e\n  errors << e.message if e.message.start_with?('Invalid type')\nend","preventionTips":["Keep a shared constant of the seven valid types in the generating system.","Only enrollments/assignments etc. are not re-keyable via change_sis_id — use the regular SIS CSV flow for those.","Normalize case/whitespace on both sides before comparing types."],"tags":["sis","ruby","import","enum"],"backgroundTag":"invalid-enum-value","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"}