instructure/canvas-lms · error · ImportError
A new_integration_id, '#
Error message
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 What it means
check_for_conflicting_ids raises this when a non-blank new_integration_id already exists on another record of the type being changed (scope.where(integration_id: new_integration_id).exists?). Integration ids must remain unique within the account, so assigning an already-used one is rejected and no update occurs.
Solutions
- Clear the integration_id on the conflicting record first (new_integration_id '<delete>' on that record), then assign it.
- Query scope.where(integration_id: new_integration_id).exists? before submitting to detect the holder.
- Deduplicate rows in the importing system to avoid replays.
Example fix
// before course,C1,C2,,INT-DUP // after: free INT-DUP first course,C-SRC,,,<delete> course,C1,C2,,INT-DUP
Defensive patterns
Strategy: validation
Validate before calling
if dc.new_integration_id.present? && scope_for(dc.type).where(integration_id: dc.new_integration_id).exists? raise ArgumentError, 'new_integration_id already in use' end process_change_sis_id(dc)
Try / catch
begin
process_change_sis_id(dc)
rescue SIS::ImportError => e
logger.warn("integration_id collision: #{e.message}")
end Prevention
- Reserve integration_ids centrally so two systems cannot allocate the same one.
- Free an integration_id with new_integration_id '<delete>' before reassigning it.
- Detect replays by tracking applied change rows.
When it happens
Trigger: change_sis_id row where new_integration_id matches an existing row's integration_id — e.g. moving an integration_id from record X to record Y while X still holds it, or replaying a previously applied change.
Common situations: Two SIS systems writing the same integration_id, idempotent re-imports, or re-pointing an integration id during a migration without clearing it from the source record first.
Related errors
- A new_id, '# ', referenced an existing # and the # with #…
- 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…
- An old_integration_id, '#
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/f7cbe4d3108ce574.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/change_sis_id_importer.rb:131
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_item
return old_item
end
if data_change.old_id.present? && data_change.old_integration_id.blank?
raise ImportError, "An old_id, '#{data_change.old_id}', referenced a non-existent #{type} and was not changed." unless old_item
return old_itemView on GitHub (pinned to 1c9f0bb801)