instructure/canvas-lms · error · ImportError
# (user # , login # )
Error message
#{user.errors.first.join(" ")} (user #{user_row.user_id}, login #{user_row.login_id}) What it means
SisImports::ImportError raised in SIS::UserImporter#process_batch when user.save fails ActiveRecord validation. The first validation error message is formatted with the row's sis user_id and login_id via generate_user_warning, then raised so the whole row is recorded as a batch error.
Solutions
- Read the validation message embedded in the error (before the '(user X, login Y)' suffix) to see which attribute failed
- Shorten or correct the offending CSV field (typically full_name/sortable_name) and re-run the import
- Strip whitespace/control characters from name columns in the source data
- If a validation was recently added/tightened, fix existing records or adjust the constraint
Example fix
// before (users.csv) user_id,full_name 1001,<255+ character name string...> // after user_id,full_name 1001,Reasonably Short Name
Defensive patterns
Strategy: try-catch
Validate before calling
if user.name.to_s.strip.length > 255 raise 'full_name exceeds 255 chars' end
Try / catch
begin
importer.add_user(row)
rescue SisImports::ImportError => e
if e.message =~ /^(.+) \(user (.+), login (.+)\)$/
logger.warn("User validation failed for sis_id=#{$2}: #{$1}")
else
raise
end
end Prevention
- Cap name fields at the DB column length (255) when generating CSVs
- Strip control/whitespace characters from name columns
- Dry-run imports in a test account before production
When it happens
Trigger: During process_batch (invoked from add_user), an existing or new User fails validation on save — e.g. name exceeding length limits, invalid characters in name fields, or any User model validation failure. The importer reads user.errors.first and aborts the row.
Common situations: CSV names longer than the users.name column limit (255 chars); names containing only whitespace or invalid characters after the importer's parsing; invalid email/other column data bleeding into user attributes; locale/config changes that tighten validations between imports.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- A user did not pass validation
- # (user # , login # )
- An email did not pass validation
- An institutional tag category did not pass validation
- Cannot find # for ID: #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/0ba39a6363660ae5.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/user_importer.rb:345
pseudo.sis_ssha = user_row.ssha_password unless user_row.ssha_password.blank?
pseudo.reset_persistence_token if pseudo.sis_ssha_changed? && pseudo.password_auto_generated
user_touched = false
user.sortable_name_explicitly_set = true if user_row.sortable_name.present?
begin
User.transaction(requires_new: true) do
sticky_opts = user.sis_stickiness_options
if user.changed? || (sticky_opts[:override_sis_stickiness] && sticky_opts[:clear_sis_stickiness] &&
user["stuck_sis_fields"].present?)
user_touched = true
user_changed = user.changed?
user_saved = user.save
# need to call save first so we can get the user id
record_sync_for(user) if user_saved && user_changed
if !user_saved && !user.errors.empty?
message = generate_user_warning(user.errors.first.join(" "), user_row.user_id, user_row.login_id)
raise ImportError, message
end
elsif @batch
@users_to_set_sis_batch_ids << user.id
end
pseudo.user_id = user.id
if pseudo.changed?
pseudo.sis_batch_id = @batch.id if @batch
if pseudo.save_without_broadcasting
record_sync_for(user)
p_data = SisBatchRollBackData.build_data(sis_batch: @batch, context: pseudo)
@roll_back_data << p_data if p_data
elsif !pseudo.errors.empty?
message = generate_user_warning(pseudo.errors.first.full_message, user_row.user_id, user_row.login_id)
raise ImportError, message
end
end
end
rescue ImportErrorView on GitHub (pinned to 1c9f0bb801)