instructure/canvas-lms · error · ImportError
No user_id given for a user
Error message
No user_id given for a user
What it means
SisImporter#add_user validates each SIS::Models::User before batching it for import. The very first check requires a non-blank user_id (the SIS identifier used to match/create the user). If user.user_id is nil or empty, an SisImports::ImportError-style ImportError is raised immediately so the batch is never queued with an unidentifiable record.
Solutions
- Ensure the source record has a user_id before calling add_user: skip or fix rows with a blank user_id
- Verify your CSV/XML header or parser maps the id column to Models::User#user_id
- Default or derive user_id from a login/email upstream if the export truly lacks it
- Wrap add_user calls in error handling so one bad row can be logged and the import continued
Example fix
// before
sis_users.each { |u| importer.add_user(u) }
// after
sis_users.each do |u|
next if u.user_id.blank?
importer.add_user(u)
end Defensive patterns
Strategy: validation
Validate before calling
raise 'user_id required' if user.respond_to?(:user_id) && user.user_id.blank? importer.add_user(user) if user.user_id.present?
Type guard
def importable_user?(u) u.is_a?(Sis::Models::User) && u.user_id.present? end
Try / catch
begin
importer.add_user(user)
rescue SisImports::ImportError => e
Rails.logger.warn("skipping user row: #{e.message}")
end Prevention
- Validate every source row's user_id before building Models::User
- Keep CSV/XML headers mapped explicitly to Models::User fields
- Unit-test the parser against exports with missing cells
When it happens
Trigger: Calling importer.add_user(user) with a SIS::Models::User built from a CSV/XML row whose user_id column (or <user_id> element) is blank; constructing Models::User manually and omitting user_id; a parser mapping that drops the user_id field.
Common situations: SIS export files with a missing/empty user_id cell; custom integration scripts building user rows by hand; schema drift after SIS export format changes leaving the id column unnamed.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- No type given for change_sis_id
- 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/0b702a3615c59a15.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/user_importer.rb:75
@batch = batch
@root_account = root_account
@logger = logger
@batched_users = []
@messages = messages
@success_count = 0
@roll_back_data = []
@users_to_set_sis_batch_ids = []
@pseudos_to_set_sis_batch_ids = []
@users_to_add_account_associations = []
@users_to_update_account_associations = []
@users_to_sync = Set.new
@authentication_providers = {}
end
# Pass a single instance of SIS::Models::User
def add_user(user, login_only: false)
raise ImportError, "No user_id given for a user" if user.user_id.blank?
raise ImportError, "No login_id given for user #{user.user_id}" if user.login_id.blank?
raise ImportError, "No status given for user #{user.user_id}" if user.status.blank?
raise ImportError, "Improper status for user #{user.user_id}" unless user.status.match?(/\A(active|suspended|deleted)/i)
return if @batch.skip_deletes? && user.status.match?(/deleted/i)
if login_only && user.existing_user_id.blank? && user.existing_integration_id.blank? && user.existing_canvas_user_id.blank?
raise ImportError, I18n.t("No existing user provided for login with SIS ID %{user_id}", user_id: user.user_id)
end
@batched_users << user
process_batch(login_only:) if @batched_users.size >= BATCH_SIZE
end
def any_left_to_process?
!@batched_users.empty?
end
def infer_user_name(user_row, prior_name = nil)View on GitHub (pinned to 1c9f0bb801)