instructure/canvas-lms · error · ImportError

Improper status "# " for account # , skipping

Error message

Improper status "#{status}" for account #{account_id}, skipping

What it means

For a new account (no existing record found by sis_source_id), the status must match /\A(active|deleted)/i; otherwise ImportError is raised. Only the two workflow states Canvas supports for accounts are accepted when creating a sub-account from SIS.

Solutions

  1. Set the status to 'active' or 'deleted' for new accounts in the SIS CSV.
  2. Map non-Canvas statuses to active/deleted before import.
  3. If the account exists already, note status validation is skipped (any status string just results in no workflow change), so aligning the value still matters for consistency.

Example fix

// before
add_account('sub3', 'parent1', 'inactive', 'Sub', nil)
// after
add_account('sub3', 'parent1', 'active', 'Sub', nil)
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, "status must be active|deleted" unless %w[active deleted].include?(status.to_s.strip.downcase)

Try / catch

begin
  importer.add_account(id, parent_id, status, name, integration_id)
rescue SIS::BaseImporter::ImportError => e
  logger.warn("#{e.message}")
end

Prevention

When it happens

Trigger: add_account with a status like 'suspended', 'inactive', 'pending', or blank for an account_id that doesn't yet exist under the root account.

Common situations: Source systems exporting richer status enums than Canvas supports; translated status strings; blank status cells in accounts.csv for new accounts.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at lib/sis/account_importer.rb:69

      def add_account(account_id, parent_account_id, status, name, integration_id)
        raise ImportError, "No account_id given for an account" if account_id.blank?
        return if @batch.skip_deletes? && status =~ /deleted/i

        parent = nil
        unless parent_account_id.blank?
          parent = @accounts_cache[parent_account_id]
          parent ||= @root_account.all_accounts.find_by(sis_source_id: parent_account_id)
          raise ImportError, "Parent account didn't exist for #{account_id}" unless parent
          raise ImportError, "Cannot restore sub_account with ID: #{account_id} because parent_account with ID: #{parent_account_id} has been deleted." if parent.workflow_state == "deleted"

          @accounts_cache[parent.sis_source_id] = parent
        end

        account = @accounts_cache[account_id]
        account ||= @root_account.all_accounts.find_by(sis_source_id: account_id)
        if account.nil?
          raise ImportError, "No name given for account #{account_id}, skipping" if name.blank?
          raise ImportError, "Improper status \"#{status}\" for account #{account_id}, skipping" unless /\A(active|deleted)/i.match?(status)
        end

        account ||= @root_account.sub_accounts.new

        account.root_account = @root_account
        if account.new_record? || !account.stuck_sis_fields.include?(:parent_account_id) || Account.sis_stickiness_options[:add_sis_stickiness]
          account.parent_account = parent || @root_account
        end

        # only update the name on new records, and ones that haven't been changed since the last sis import
        account.name = name if name.present? && (account.new_record? || !account.stuck_sis_fields.include?(:name))

        account.integration_id = integration_id if integration_id.present?
        account.sis_source_id = account_id

        if status.present?
          case status
          when /active/i

View on GitHub (pinned to 1c9f0bb801)