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
- Have the user re-enroll MFA (factor is incomplete on the server) and retry login
- Verify the backend MFA-check endpoint returns both factorId and factorType when required=true
- Check @tm/core and server API versions match; upgrade @tm/core to the latest
- Inspect the logged mfaCheck object (logger.error output) to see which field is missing
- 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
- Keep @tm/core and the server API on compatible versions
- Re-enroll MFA promptly if a factor shows as incomplete in account settings
- Monitor server logs for mfaCheck payloads missing factorId/factorType
- Add an integration test asserting the MFA-check endpoint always returns both fields when required=true
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.