medusajs/medusa · error · MedusaError

MFA challenge does not support method "${method}"

Error message

MFA challenge does not support method "${method}"

What it means

Raised when verifying an MFA challenge with a method that is not in the challenge's allowed methods list (e.g. the challenge was created for 'totp' but verification uses 'recovery_code'). INVALID_DATA — the request mismatches the challenge configuration.

Source

Thrown at packages/modules/auth/src/services/auth-module.ts:848

      )
    }

    if (new Date(challenge.expires_at).getTime() <= Date.now()) {
      throw new MedusaError(
        MedusaError.Types.NOT_ALLOWED,
        "MFA challenge has expired"
      )
    }

    if (challenge.attempts >= challenge.max_attempts) {
      throw new MedusaError(
        MedusaError.Types.NOT_ALLOWED,
        "MFA challenge has too many failed attempts"
      )
    }

    if (!challenge.methods.includes(method)) {
      throw new MedusaError(
        MedusaError.Types.INVALID_DATA,
        `MFA challenge does not support method "${method}"`
      )
    }
  }

  @InjectManager()
  async createPasswordResetToken(
    data: AuthTypes.CreatePasswordResetTokenDTO,
    @MedusaContext() sharedContext: Context = {}
  ): Promise<AuthTypes.CreatePasswordResetTokenResponse> {
    return await this.createPasswordResetToken_(data, sharedContext)
  }

  @InjectTransactionManager()
  protected async createPasswordResetToken_(
    data: AuthTypes.CreatePasswordResetTokenDTO,
    @MedusaContext() sharedContext: Context = {}

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Send verification with the same method(s) the challenge was created with
  2. Create a separate challenge for recovery-code verification if the flow needs it
  3. Inspect the challenge DTO's methods array before choosing what to submit

Example fix

// before
await authModule.verifyAuthMfaChallenge({ challenge_id, method: 'recovery_code', body })
// after
const challenge = await authModule.retrieveAuthMfaChallenge(challenge_id)
await authModule.verifyAuthMfaChallenge({ challenge_id, method: challenge.methods[0], body })
Defensive patterns

Strategy: validation

Validate before calling

const challenge = await authModule.retrieveAuthMfaChallenge(challengeId)
if (!challenge.methods.includes(method)) throw new Error(`Use one of: ${challenge.methods.join(', ')}`)

Type guard

const isSupportedMethod = (m: string, challenge: AuthMfaChallengeDTO): boolean => challenge.methods.includes(m)

Try / catch

null

Prevention

When it happens

Trigger: Passing method: 'recovery_code' to a challenge created only for 'otp'/'totp'; frontend hardcoding the wrong method name; copy-paste between flows using different methods.

Common situations: Multi-method MFA UIs where the user switches entry mode but the challenge is method-scoped; method string typos or casing differences.

Related errors


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