instructure/canvas-lms · error · ImportError
Group categories should not have integration IDs.
Error message
Group categories should not have integration IDs.
What it means
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.
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.
Example fix
// before type,old_id,new_id,old_integration_id group_category,GC1,GC2,INT1 // after type,old_id,new_id group_category,GC1,GC2
Defensive patterns
Strategy: validation
Validate before calling
if dc.type.to_s.downcase.strip == 'group_category' && (dc.old_integration_id.present? || dc.new_integration_id.present?) raise ArgumentError, 'group_category rows must not carry integration ids' end process_change_sis_id(dc)
Try / catch
begin process_change_sis_id(dc) rescue SIS::ImportError => e errors << e.message end
Prevention
- 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.
When it happens
Trigger: A change_sis_id row with type=group_category whose old_integration_id or new_integration_id column is non-empty.
Common situations: 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.
Related errors
- A new_id, '# ', referenced an existing # and the # with #…
- A new_integration_id, '#
- A student referenced a non-existent user #
- An old_id, '# ', referenced a different # than the…
- An old_id, '# ', referenced a non-existent # and was not…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/a07ef95b487d9ee5.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/change_sis_id_importer.rb:124
end
def ids_to_change(column, data_change)
updates = {}
if data_change.new_id.present?
updates[column] = data_change.new_id
end
if data_change.new_integration_id.present?
updates["integration_id"] = data_change.new_integration_id
if data_change.new_integration_id == "<delete>"
updates["integration_id"] = nil
end
end
updates
end
def check_for_conflicting_ids(column, details, type, data_change)
if type == "group_category" && (data_change.old_integration_id || data_change.new_integration_id)
raise ImportError, "Group categories should not have integration IDs."
end
check_new = details[:scope].where(column => data_change.new_id).exists? if data_change.new_id.present?
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
check_int = details[:scope].where(integration_id: data_change.new_integration_id).exists? if data_change.new_integration_id.present?
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
end
def find_item_to_update(column, details, type, data_change)
if data_change.old_id.present?
old_item = details[:scope].find_by(column => data_change.old_id)
end
if data_change.old_integration_id.present?
old_int_item = details[:scope].find_by(integration_id: data_change.old_integration_id)
end
if data_change.old_id.present? && data_change.old_integration_id.present?
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_itemView on GitHub (pinned to 1c9f0bb801)