{"record":{"id":"5c4e1a91b955a4fa","repo":"medusajs/medusa","slug":"mfa-challenge-has-too-many-failed-attempts","errorCode":null,"errorMessage":"MFA challenge has too many failed attempts","messagePattern":"MFA challenge has too many failed attempts","errorType":"exception","errorClass":"MedusaError","httpStatus":403,"severity":"error","filePath":"packages/modules/auth/src/services/auth-module.ts","lineNumber":500,"sourceCode":"\n    const valid = await this.authMfaProviderService_.verify(\n      data.method,\n      {\n        auth_identity_id: challenge.auth_identity_id!,\n        code: data.code,\n      },\n      sharedContext\n    )\n\n    if (!valid) {\n      const attempts = challenge.attempts + 1\n\n      await this.setMfaChallenge_({\n        ...challenge,\n        attempts,\n      })\n\n      throw new MedusaError(\n        MedusaError.Types.NOT_ALLOWED,\n        attempts >= challenge.max_attempts\n          ? \"MFA challenge has too many failed attempts\"\n          : \"Invalid MFA challenge code\"\n      )\n    }\n\n    const completedChallenge: AuthTypes.AuthMfaChallengeDTO = {\n      ...challenge,\n      completed_at: new Date(),\n    }\n\n    await this.setMfaChallenge_(completedChallenge)\n\n    return completedChallenge\n  }\n\n  @InjectManager()","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/modules/auth/src/services/auth-module.ts#L482-L518","documentation":"Verifying an MFA challenge failed and the attempt counter reached max_attempts, so the challenge is locked and the specific 'too many failed attempts' message is thrown (the counter is persisted via setMfaChallenge_ before throwing).","triggerScenarios":"verifyAuthMfaChallenge with wrong codes until attempts >= challenge.max_attempts (configured via MFA challenge config). Each wrong attempt increments the persisted counter.","commonSituations":"Brute-force guessing or a user repeatedly entering stale codes; authenticator drift making every attempt fail until lockout; automated tests hammering the endpoint.","solutions":["Start a new MFA challenge (createAuthMfaChallenge) to get a fresh counter and code","Fix the underlying code generation issue (device time sync) before retrying","Treat lockout as a signal to rate-limit/cool down at the route level"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await verifyAuthMfaChallenge(...) } catch (e) { if (e.message.includes('too many failed attempts')) { await createAuthMfaChallenge(...) /* fresh challenge */ } throw e }","preventionTips":["Show remaining attempts before lockout","Rate-limit verify attempts at the route level","Fix code-generation issues (time sync) early"],"tags":["auth","mfa","rate-limit","lockout"],"backgroundTag":"mfa-challenge-locked","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}