instructure/canvas-lms · error · ImportError
An old_integration_id, '#
Error message
An old_integration_id, '#{data_change.old_integration_id}', referenced a non-existent #{type} and was not changed. What it means
find_item_to_update raises this when old_id is blank, old_integration_id is present, and no record matches scope.find_by(integration_id => old_integration_id). The record identified only by its integration_id does not exist in the root-account scope, so no re-keying is possible.
Solutions
- Verify the integration_id exists: scope.where(integration_id: old_integration_id).exists?.
- Fall back to identifying the record via old_id instead.
- Refresh the export so the integration_id matches Canvas's current data.
Example fix
// before: integration_id not in Canvas user,,new-id,INT-404 // after: use the id Canvas actually has user,U-100,new-id
Defensive patterns
Strategy: validation
Validate before calling
if dc.old_id.blank? && dc.old_integration_id.present?
unless scope_for(dc.type).where(integration_id: dc.old_integration_id).exists?
raise ArgumentError, "unknown integration_id #{dc.old_integration_id}"
end
end
process_change_sis_id(dc) Try / catch
begin
process_change_sis_id(dc)
rescue SIS::ImportError => e
if e.message.include?('old_integration_id')
logger.warn("unknown integration_id=#{dc.old_integration_id}: skipped")
end
end Prevention
- Confirm Canvas actually stores the external system's id as integration_id for that type.
- Prefer old_id lookups; integration_id lookups are fragile to reassignment.
- Validate integration_ids against the current DB before generating change rows.
When it happens
Trigger: change_sis_id row relying solely on old_integration_id where no row of the type has that integration_id — record deleted, integration_id already changed/cleared, or wrong account.
Common situations: External SIS sends its own ids assuming Canvas stored them as integration_id, stale exports after integration_id reassignment, or type mismatch (integration_id looked up in the wrong scope for the declared type).
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- An old_id, '# ', referenced a non-existent # and was not…
- 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…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/716736c2557cfc02.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/change_sis_id_importer.rb:152
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_item
end
if data_change.old_id.blank? && data_change.old_integration_id.present?
raise ImportError, "An old_integration_id, '#{data_change.old_integration_id}', referenced a non-existent #{type} and was not changed." unless old_int_item
old_int_item
end
end
end
end
end
View on GitHub (pinned to 1c9f0bb801)