{"record":{"id":"2224eebbe056b879","repo":"medusajs/medusa","slug":"only-totp-mfa-factors-can-be-verified-with-this-me","errorCode":null,"errorMessage":"Only TOTP MFA factors can be verified with this method","messagePattern":"Only TOTP MFA factors can be verified with this method","errorType":"exception","errorClass":"MedusaError","httpStatus":400,"severity":"error","filePath":"packages/modules/auth/src/providers/mfa/totp.ts","lineNumber":132,"sourceCode":"        secret,\n        digits: totpConfig.digits,\n        period: totpConfig.period,\n      }),\n    }\n  }\n\n  async verifySetup(\n    data: AuthTypes.AuthMfaVerifyDTO,\n    sharedContext: Context = {}\n  ): Promise<AuthTypes.AuthMfaDTO> {\n    const factor = await this.authMfaFactorService_.retrieve(\n      data.id,\n      {},\n      sharedContext\n    )\n\n    if (factor.provider !== this.method) {\n      throw new MedusaError(\n        MedusaError.Types.INVALID_DATA,\n        \"Only TOTP MFA factors can be verified with this method\"\n      )\n    }\n\n    if (factor.status === \"disabled\") {\n      throw new MedusaError(\n        MedusaError.Types.NOT_ALLOWED,\n        \"Disabled MFA factors cannot be verified\"\n      )\n    }\n\n    const valid = this.verifyCode_(factor, data.code)\n\n    if (!valid) {\n      throw new MedusaError(MedusaError.Types.NOT_ALLOWED, \"Invalid TOTP code\")\n    }\n","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/modules/auth/src/providers/mfa/totp.ts#L114-L150","documentation":"verifySetup on the TOTP provider only verifies factors whose provider is 'totp'. Passing the id of a factor created by a different MFA provider (e.g. another OTP method) throws INVALID_DATA.","triggerScenarios":"confirmAuthMfaFactor / verifySetup({ id }) where the factor row's provider column is not 'totp' — e.g. ids mixed up between provider setups or a generic confirm route hardcoded to the totp provider.","commonSituations":"Frontend sends a factor id from the wrong provider after multiple MFA methods are enabled; copy-pasted factor ids between environments.","solutions":["Fetch the factor and route verification to the provider stored on it (factor.provider)","Check that the factor id passed corresponds to a TOTP setup"],"exampleFix":"// before\nawait totpProvider.verifySetup({ id: factorId, code })\n// after\nconst [factor] = await authModuleService.listAuthMfaFactors(identityId)\nconst provider = factor.provider // route to matching provider\nawait mfaProviderService.verifySetup(factor.provider, { id: factor.id, code })","handlingStrategy":"type-guard","validationCode":"const [factor] = await authModuleService.listAuthMfaFactors(identityId)\nif (factor.provider !== 'totp') throw new Error('route to the correct provider')","typeGuard":"const isTotpFactor = (f: { provider: string }) => f.provider === 'totp'","tryCatchPattern":null,"preventionTips":["Always dispatch verification to the provider stored on the factor row","Don't hardcode provider names in generic confirm routes"],"tags":["auth","mfa","totp","validation"],"backgroundTag":"wrong-provider","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}