instructure/canvas-lms · error · ImportError

No status given for user #

Error message

No status given for user #{user.user_id}

What it means

add_user validates that user.status is present. Status (active/suspended/deleted) drives whether the user is created, deactivated, or deleted, so a blank status is ambiguous and rejected with an ImportError citing the user's user_id.

Solutions

  1. Set status explicitly ('active', 'suspended', or 'deleted') on every user record
  2. Default missing statuses to 'active' only if that is safe for your data contract
  3. Fix the upstream export so status is always populated
  4. Skip and report rows with blank status instead of feeding them to add_user

Example fix

// before
importer.add_user(Sis::Models::User.new(user_id: id, login_id: login))
// after
importer.add_user(Sis::Models::User.new(user_id: id, login_id: login, status: row['status'].presence || 'active'))
Defensive patterns

Strategy: validation

Validate before calling

user.status = 'active' if user.status.blank?
importer.add_user(user)

Type guard

def has_status?(u)
  u.is_a?(Sis::Models::User) && u.status.present?
end

Try / catch

begin
  importer.add_user(user)
rescue SisImports::ImportError => e
  Rails.logger.warn("user #{user.user_id}: #{e.message}")
end

Prevention

When it happens

Trigger: Calling add_user with a Models::User whose status field is nil or '' — e.g. CSV rows missing the status column, or an export that omits status for new users.

Common situations: Hand-rolled scripts that forget to set status; SIS exports with an empty status cell; parsers that read a status column that no longer exists in the header.

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


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/c7cdbeae384a6f5d. Report an issue: GitHub.

Appendix: source

Thrown at lib/sis/user_importer.rb:77

        @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)
        if user_row.full_name.present?
          user_row.full_name

View on GitHub (pinned to 1c9f0bb801)