medusajs/medusa · error · MedusaError

Email is required to create a customer

Error message

Email is required to create a customer

What it means

validateCustomerAccountCreationStep requires customerData.email before creating a customer account; without an email the account cannot be linked to an auth identity.

Source

Thrown at packages/core/core-flows/src/customer/steps/validate-customer-account-creation.ts:34

 * @example
 * const data = validateCustomerAccountCreation({
 *   authIdentityId: "au_1234",
 *   customerData: {
 *     first_name: "John",
 *     last_name: "Doe",
 *     email: "john.doe@example.com",
 *   }
 * })
 */
export const validateCustomerAccountCreation = createStep(
  validateCustomerAccountCreationStepId,
  async (input: CreateCustomerAccountWorkflowInput, { container }) => {
    const customerService = container.resolve(Modules.CUSTOMER)

    const { email } = input.customerData

    if (!email) {
      throw new MedusaError(
        MedusaError.Types.INVALID_DATA,
        "Email is required to create a customer"
      )
    }

    // Check if customer with email already exists
    const existingCustomers = await customerService.listCustomers({ email })

    if (existingCustomers?.length) {
      const hasExistingAccount = existingCustomers.some(
        (customer) => customer.has_account
      )

      if (hasExistingAccount && input.authIdentityId) {
        throw new MedusaError(
          MedusaError.Types.DUPLICATE_ERROR,
          "Customer with this email already has an account"
        )

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Include a non-empty email in input.customerData
  2. Validate the request body with a schema (require email, validate format) before invoking the workflow
  3. If creating a guest customer, use createCustomerWorkflow or the store-customer route instead of the account workflow

Example fix

// before
await createCustomerAccountWorkflow(container).run({
  input: { customerData: { first_name: "A" }, authIdentityId },
})

// after
await createCustomerAccountWorkflow(container).run({
  input: { customerData: { first_name: "A", email: "a@b.com" }, authIdentityId },
})
Defensive patterns

Strategy: validation

Validate before calling

if (!input?.customerData?.email?.trim()) throw new Error("Email is required")

Type guard

const hasEmail = (i?: { customerData?: { email?: string } }) => !!i?.customerData?.email?.trim()

Try / catch

try { await createCustomerAccountWorkflow(scope).run({ input }) } catch (e) { if (e.type === MedusaError.Types.INVALID_DATA && /Email is required/.test(e.message)) { return badRequest("email is required") } throw e }

Prevention

When it happens

Trigger: Calling createCustomerAccountWorkflow with customerData that has no email (undefined or empty string).

Common situations: Signup form submitted without email; email field named differently in client payload; guest-checkout code path reusing the account-creation workflow by mistake; trimming email to empty before passing through.

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/e893ef66516f18a2. Report an issue: GitHub.