eyaltoledano/claude-task-master · error · AuthenticationError

MFA_VERIFICATION_FAILED

MFA_VERIFICATION_FAILED

Error message

`MFA verification failed: ${(error as Error).message}`

What it means

This error is thrown by SessionManager.verifyMFA when the MFA verification flow fails with an unexpected error. If the underlying failure is already an AuthenticationError it is re-thrown as-is; otherwise it is wrapped in a new AuthenticationError with code MFA_VERIFICATION_FAILED. It signals that multi-factor authentication could not be completed during login.

Source

Thrown at packages/tm-core/src/modules/auth/services/session-manager.ts:356

				token: session.access_token,
				refreshToken: session.refresh_token,
				userId: user.id,
				email: user.email,
				expiresAt: session.expires_at
					? new Date(session.expires_at * 1000).toISOString()
					: undefined,
				tokenType: 'standard',
				savedAt: new Date().toISOString(),
				selectedContext: context || undefined
			};

			this.logger.info('Successfully verified MFA and authenticated');
			return credentials;
		} catch (error) {
			if (error instanceof AuthenticationError) {
				throw error;
			}
			throw new AuthenticationError(
				`MFA verification failed: ${(error as Error).message}`,
				'MFA_VERIFICATION_FAILED'
			);
		}
	}

	// ========== Session Lifecycle ==========

	/**
	 * Logout and clear credentials
	 */
	async logout(): Promise<void> {
		await this.waitForInitialization();
		try {
			// First try to sign out from Supabase to revoke tokens
			await this.supabaseClient.signOut();
		} catch (error) {
			// Log but don't throw - we still want to clear local credentials

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Re-request a fresh MFA code and verify it promptly before it expires
  2. Check network connectivity and Supabase service status, then retry
  3. Confirm the authenticator app time sync (TOTP drift) and re-enroll MFA if codes consistently fail
  4. Inspect the wrapped cause message to identify the underlying provider error

Example fix

// before
await sessionManager.verifyMFA('123456');
// after
try {
  await sessionManager.verifyMFA(await promptFreshTotpCode());
} catch (e) {
  if (e instanceof AuthenticationError && e.code === 'MFA_VERIFICATION_FAILED') {
    await sessionManager.requestMfaChallenge(); // get a new code, then retry
  } else { throw e; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before verifying, ensure a code was entered and a challenge is active
if (!code || !/^\d{6}$/.test(code.trim())) throw new Error('Enter the 6-digit MFA code');
if (!sessionManager.hasPendingChallenge()) await sessionManager.requestMfaChallenge();

Type guard

function isAuthenticationError(e: unknown): e is AuthenticationError {
  return e instanceof AuthenticationError;
}

Try / catch

try {
  await sessionManager.verifyMFA(code);
} catch (e) {
  if (isAuthenticationError(e) && e.code === 'MFA_VERIFICATION_FAILED') {
    // prompt for a fresh code / check connectivity, then retry once
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling verifyMFA (directly or via the credentials/session flows) when the MFA code is wrong/expired, the Supabase challenge verify call throws, or any non-AuthenticationError (network, malformed response) escapes the try block.

Common situations: User types an outdated 6-digit code after requesting a new one; authenticator app clock drift causing TOTP mismatch; network outage or Supabase outage mid-login; Supabase client returning an error object that is not an AuthenticationError.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/80f2de2a47288d93. Report an issue: GitHub.