eyaltoledano/claude-task-master · error · AuthenticationError

MFA_REQUIRED_INCOMPLETE

MFA_REQUIRED_INCOMPLETE

Error message

'MFA is required but the server returned incomplete factor configuration. Please contact support or try re-enrolling MFA.'

What it means

Thrown by checkAndThrowIfMFARequired in OAuthService when the backend signals that MFA is required after an OAuth/PKCE login, but the MFA challenge response is missing factorId or factorType. Without both fields the library cannot construct a valid MFAChallenge, so instead of asking the user for a code it fails fast with MFA_REQUIRED_INCOMPLETE. This indicates a server-side contract violation rather than a user error.

Source

Thrown at packages/tm-core/src/modules/auth/services/oauth-service.ts:456

	 */
	getAuthorizationUrl(): string | null {
		return this.authorizationUrl;
	}

	/**
	 * Check if MFA is required and throw appropriate error if so
	 * This ensures OAuth flow enforces MFA when user has it enabled
	 */
	private async checkAndThrowIfMFARequired(): Promise<void> {
		const mfaCheck = await this.supabaseClient.checkMFARequired();

		if (mfaCheck.required) {
			// MFA is required - check if we have complete factor information
			if (!mfaCheck.factorId || !mfaCheck.factorType) {
				this.logger.error('MFA required but factor information is incomplete', {
					mfaCheck
				});
				throw new AuthenticationError(
					'MFA is required but the server returned incomplete factor configuration. Please contact support or try re-enrolling MFA.',
					'MFA_REQUIRED_INCOMPLETE'
				);
			}

			this.logger.info('MFA verification required after OAuth login', {
				factorId: mfaCheck.factorId,
				factorType: mfaCheck.factorType
			});

			const mfaChallenge: MFAChallenge = {
				factorId: mfaCheck.factorId,
				factorType: mfaCheck.factorType
			};

			throw new AuthenticationError(
				'MFA verification required. Please provide your authentication code.',
				'MFA_REQUIRED',

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Have the user re-enroll MFA (factor is incomplete on the server) and retry login
  2. Verify the backend MFA-check endpoint returns both factorId and factorType when required=true
  3. Check @tm/core and server API versions match; upgrade @tm/core to the latest
  4. Inspect the logged mfaCheck object (logger.error output) to see which field is missing
  5. Retry authentication once in case of a transient server-side read glitch

Example fix

// before: user stuck with incomplete factor data
await tmCore.auth.loginWithOAuth();
// after: detect incomplete MFA and prompt re-enrollment
try {
  await tmCore.auth.loginWithOAuth();
} catch (e) {
  if (e instanceof AuthenticationError && e.code === 'MFA_REQUIRED_INCOMPLETE') {
    console.error('Re-enroll MFA at https://server/mfa, then retry login');
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// No client-side pre-check possible; the defect is in the server payload.
// Validate the challenge AFTER catching, before continuing the MFA flow:
function hasCompleteChallenge(e: unknown): e is AuthenticationError & { details: { factorId: string; factorType: string } } {
  return e instanceof AuthenticationError &&
    e.code === 'MFA_REQUIRED' &&
    typeof (e.details as any)?.factorId === 'string' &&
    typeof (e.details as any)?.factorType === 'string';
}

Type guard

function isIncompleteMfaError(e: unknown): e is AuthenticationError {
  return e instanceof AuthenticationError && e.code === 'MFA_REQUIRED_INCOMPLETE';
}

Try / catch

try {
  await tmCore.auth.loginWithOAuth();
} catch (e) {
  if (isIncompleteMfaError(e)) {
    console.error('Server returned incomplete MFA config. Re-enroll MFA and retry.', e.code);
    // surface to user: direct them to re-enrollment, do not prompt for a code
  } else throw e;
}

Prevention

When it happens

Trigger: authenticateWithBackendPKCE completes OAuth and calls the MFA-check endpoint; the response has required=true but factorId or factorType is missing/null/undefined (e.g. a factor row missing from Supabase MFA config, a malformed mfaCheck payload, or an API version returning a different shape).

Common situations: Backend API updated and changed the MFA response shape; user's MFA factor was partially deleted or never fully enrolled so the server reports required without factor details; proxy/gateway stripping fields; mismatched @tm/core and server versions.

Related errors


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