{"record":{"id":"a07ef95b487d9ee5","repo":"instructure/canvas-lms","slug":"group-categories-should-not-have-integration-ids","errorCode":null,"errorMessage":"Group categories should not have integration IDs.","messagePattern":"Group categories should not have integration IDs\\.","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/change_sis_id_importer.rb","lineNumber":124,"sourceCode":"      end\n\n      def ids_to_change(column, data_change)\n        updates = {}\n        if data_change.new_id.present?\n          updates[column] = data_change.new_id\n        end\n        if data_change.new_integration_id.present?\n          updates[\"integration_id\"] = data_change.new_integration_id\n          if data_change.new_integration_id == \"<delete>\"\n            updates[\"integration_id\"] = nil\n          end\n        end\n        updates\n      end\n\n      def check_for_conflicting_ids(column, details, type, data_change)\n        if type == \"group_category\" && (data_change.old_integration_id || data_change.new_integration_id)\n          raise ImportError, \"Group categories should not have integration IDs.\"\n        end\n\n        check_new = details[:scope].where(column => data_change.new_id).exists? if data_change.new_id.present?\n        raise ImportError, \"A new_id, '#{data_change.new_id}', referenced an existing #{type} and the #{type} with #{column} '#{data_change.old_id}' was not updated\" if check_new\n\n        check_int = details[:scope].where(integration_id: data_change.new_integration_id).exists? if data_change.new_integration_id.present?\n        raise ImportError, \"A new_integration_id, '#{data_change.new_integration_id}', referenced an existing #{type} and the #{type} with integration_id '#{data_change.old_integration_id}' was not updated\" if check_int\n      end\n\n      def find_item_to_update(column, details, type, data_change)\n        if data_change.old_id.present?\n          old_item = details[:scope].find_by(column => data_change.old_id)\n        end\n        if data_change.old_integration_id.present?\n          old_int_item = details[:scope].find_by(integration_id: data_change.old_integration_id)\n        end\n        if data_change.old_id.present? && data_change.old_integration_id.present?\n          raise ImportError, \"An old_id, '#{data_change.old_id}', referenced a different #{type} than the old_integration_id, '#{data_change.old_integration_id}'\" unless old_item == old_int_item","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/change_sis_id_importer.rb#L106-L142","documentation":"check_for_conflicting_ids raises this when type is 'group_category' and either old_integration_id or new_integration_id is present. GroupCategory models in Canvas have no integration_id column, so integration-ID based lookups/writes are meaningless and rejected outright.","triggerScenarios":"A change_sis_id row with type=group_category whose old_integration_id or new_integration_id column is non-empty.","commonSituations":"One-size-fits-all SIS export scripts that always emit integration_id columns regardless of type, or copy-pasted rows where a group row's integration id was reused for a group_category.","solutions":["Remove the integration_id values from the group_category row; identify the record via old_id and change it via new_id only.","If an integration_id is genuinely needed, change the type to a supported entity (e.g. group) or add integration_id support upstream.","Strip integration_id columns for group_category rows in the CSV generator."],"exampleFix":"// before\ntype,old_id,new_id,old_integration_id\ngroup_category,GC1,GC2,INT1\n// after\ntype,old_id,new_id\ngroup_category,GC1,GC2","handlingStrategy":"validation","validationCode":"if dc.type.to_s.downcase.strip == 'group_category' &&\n   (dc.old_integration_id.present? || dc.new_integration_id.present?)\n  raise ArgumentError, 'group_category rows must not carry integration ids'\nend\nprocess_change_sis_id(dc)","typeGuard":null,"tryCatchPattern":"begin\n  process_change_sis_id(dc)\nrescue SIS::ImportError => e\n  errors << e.message\nend","preventionTips":["Make CSV generation type-aware: emit integration_id columns only for types that support them.","Document that group_category supports sis_source_id changes only.","Add a lint rule rejecting integration_id on group_category rows."],"tags":["sis","ruby","import","unsupported-combination"],"backgroundTag":"mutually-exclusive-options","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"}