spree/spree · error · ArgumentError

Email is required

Error message

Email is required

What it means

Spree::Imports::RowProcessors::Customer#process! raises ArgumentError 'Email is required' when a customer-import CSV row has no usable email (blank after strip). Email is the find_or_initialize_by key on Spree.customer_class, so a row without it cannot identify or create a customer and the row is rejected before any attribute is assigned.

Source

Thrown at spree/core/app/services/spree/imports/row_processors/customer.rb:17

module Spree
  module Imports
    module RowProcessors
      class Customer < Base
        def process!
          user = find_or_initialize_user
          assign_user_attributes(user)
          assign_address(user) if address_fields_present?
          user.save!
          user
        end

        private

        def find_or_initialize_user
          email = attributes['email'].to_s.strip.downcase
          raise ArgumentError, 'Email is required' if email.blank?

          Spree.customer_class.find_or_initialize_by(email: email)
        end

        def assign_user_attributes(user)
          user.first_name = attributes['first_name'].strip if attributes['first_name'].present?
          user.last_name = attributes['last_name'].strip if attributes['last_name'].present?
          user.phone = attributes['phone'].strip if attributes['phone'].present?
          user.accepts_email_marketing = to_boolean(attributes['accepts_email_marketing']) if attributes['accepts_email_marketing'].present?
          user.tag_list = attributes['tags'] if attributes['tags'].present?

          if user.new_record?
            password = SecureRandom.hex(16)
            user.password = password
            user.password_confirmation = password
          end
        end

View on GitHub (pinned to 06bf66a868)

Solutions

  1. Open the CSV and confirm a header column named exactly 'email' exists.
  2. Fill in or remove every row whose email cell is empty or whitespace-only.
  3. Re-save the file as plain UTF-8 without BOM and strip stray whitespace from headers.
  4. Re-run the import; row-level failures are reported per row, so previously imported rows are not lost.

Example fix

# before — customers.csv
first_name,last_name
Ada,Lovelace

# after
email,first_name,last_name
ada@example.com,Ada,Lovelace
Defensive patterns

Strategy: validation

Validate before calling

# before submitting a customers import, reject/repair rows without email
require 'csv'

invalid = []
CSV.table(csv_path, converters: nil).each.with_index(2) do |row, line|
  invalid << line if row[:email].to_s.strip.blank?
end
abort "Rows without email: #{invalid.join(', ')}" if invalid.any?

Try / catch

begin
  processor.process!
rescue ArgumentError => e
  # per-row failure: record line + message, keep importing the rest
  import_row.update!(status: 'failed', error_message: e.message)
end

Prevention

When it happens

Trigger: Running a customers CSV import where the 'email' column is absent from the header, empty on some row, or contains only whitespace. The processor strips and downcases attributes['email'] and raises when the result is blank.

Common situations: Exported file with a renamed or mistyped header ('Email', 'e-mail', 'email '), spreadsheet saving blank cells as empty strings, UTF-8 BOM shifting the first header, or assuming email is optional because the storefront allows guest data without it.

Related errors


AI-assisted analysis of spree/spree@06bf66a868 (2026-08-21). Data as JSON: /api/errors/6b8f242eea11c396. Report an issue: GitHub.