{"record":{"id":"156907dc280f6bae","repo":"instructure/canvas-lms","slug":"an-old-id-data-change-old-id-referenced-a-different-type","errorCode":null,"errorMessage":"An old_id, '#{data_change.old_id}', referenced a different #{type} than the old_integration_id, '#{data_change.old_integration_id}'","messagePattern":"An old_id, '#(.+?)', referenced a different #(.+?) than the old_integration_id, '#(.+?)'","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/change_sis_id_importer.rb","lineNumber":142,"sourceCode":"          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\n\n          return old_item\n        end\n        if data_change.old_id.present? && data_change.old_integration_id.blank?\n          raise ImportError, \"An old_id, '#{data_change.old_id}', referenced a non-existent #{type} and was not changed.\" unless old_item\n\n          return old_item\n        end\n        if data_change.old_id.blank? && data_change.old_integration_id.present?\n          raise ImportError, \"An old_integration_id, '#{data_change.old_integration_id}', referenced a non-existent #{type} and was not changed.\" unless old_int_item\n\n          old_int_item\n        end\n      end\n    end\n  end\nend\n","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/change_sis_id_importer.rb#L124-L160","documentation":"find_item_to_update raises this when both old_id and old_integration_id are present but they resolve to different records (old_item != old_int_item) — or one resolves to nil. The importer requires the two identifiers to agree on the same row; a disagreement means ambiguous or corrupted reference data, so the change is refused.","triggerScenarios":"A change_sis_id row where scope.find_by(sis_source_id => old_id) and scope.find_by(integration_id => old_integration_id) return different objects, or where one of the two lookups finds nothing (old_item == nil != old_int_item, or vice versa).","commonSituations":"Data drift where a record's integration_id was reassigned after the CSV was generated, copy-paste rows mixing identifiers from two records, or stale batch files referencing pre-migration data.","solutions":["Ensure old_id and old_integration_id point to the same record — or supply only one of them.","Regenerate the CSV from current data so both identifiers are in sync.","Check which record each identifier currently resolves to and correct the mismatched one."],"exampleFix":"// before: ids from different records\nuser,U1,new-id,INT-OF-OTHER-USER\n// after\nuser,U1,new-id,INT-OF-U1","handlingStrategy":"validation","validationCode":"if dc.old_id.present? && dc.old_integration_id.present?\n  a = scope.find_by(column => dc.old_id)\n  b = scope.find_by(integration_id: dc.old_integration_id)\n  raise ArgumentError, 'old_id and old_integration_id reference different records' unless a == b\nend\nprocess_change_sis_id(dc)","typeGuard":null,"tryCatchPattern":"begin\n  process_change_sis_id(dc)\nrescue SIS::ImportError => e\n  errors << e.message if e.message.include?('referenced a different')\nend","preventionTips":["Supply only one of old_id / old_integration_id unless you can guarantee they resolve to the same row.","Regenerate CSVs from current DB state rather than caching old exports.","Reconcile integration_id assignments after any migration before re-keying."],"tags":["sis","ruby","import","consistency","identifier"],"backgroundTag":"conflicting-identifier-references","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"}