{"record":{"id":"7b0480b17c053235","repo":"eyaltoledano/claude-task-master","slug":"invalid-mfa-code","errorCode":"INVALID_MFA_CODE","errorMessage":"Invalid MFA code: ${error.message}","messagePattern":"Invalid MFA code: (.+?)","errorType":"error_code","errorClass":"AuthenticationError","httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/integration/clients/supabase-client.ts","lineNumber":567,"sourceCode":"\t\t\t\tawait client.auth.mfa.challenge({ factorId });\n\n\t\t\tif (challengeError || !challengeData) {\n\t\t\t\tthrow new AuthenticationError(\n\t\t\t\t\t`Failed to create MFA challenge: ${challengeError?.message || 'Unknown error'}`,\n\t\t\t\t\t'MFA_VERIFICATION_FAILED'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Verify the TOTP code\n\t\t\tconst { data, error } = await client.auth.mfa.verify({\n\t\t\t\tfactorId,\n\t\t\t\tchallengeId: challengeData.id,\n\t\t\t\tcode\n\t\t\t});\n\n\t\t\tif (error) {\n\t\t\t\tthis.logger.error('MFA verification failed:', error);\n\t\t\t\tthrow new AuthenticationError(\n\t\t\t\t\t`Invalid MFA code: ${error.message}`,\n\t\t\t\t\t'INVALID_MFA_CODE'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (!data) {\n\t\t\t\tthrow new AuthenticationError(\n\t\t\t\t\t'No data returned from MFA verification',\n\t\t\t\t\t'INVALID_RESPONSE'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// After successful MFA verification, refresh the session to get the upgraded AAL2 session\n\t\t\tconst {\n\t\t\t\tdata: { session },\n\t\t\t\terror: refreshError\n\t\t\t} = await client.auth.refreshSession();\n","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/integration/clients/supabase-client.ts#L549-L585","documentation":"SupabaseClient.verifyMFA() throws this when `client.auth.mfa.verify({factorId, challengeId, code})` returns an error — Supabase rejected the TOTP code (or the challenge). It is surfaced as AuthenticationError with code INVALID_MFA_CODE, distinguishing a wrong/expired code from infrastructure failures.","triggerScenarios":"User enters a wrong 6-digit TOTP code; code is reused (same code used in the previous 30s window); code entered too slowly (past the validity window); challenge expired between challenge() and verify(); clock drift on the user's authenticator device.","commonSituations":"Typo'd or stale authenticator code; copying an old code from an authenticator app list; system clock skew on phone or machine; prompting for MFA, waiting (e.g. CI job paused), then submitting after challenge expiry.","solutions":["Ask the user to re-enter the current 6-digit code from the authenticator app (prompt for a fresh challenge on retry).","Create a new challenge before each verification attempt — challenges expire; never reuse a challengeId.","Check authenticator device clock sync (TOTP depends on accurate time).","Verify the code is submitted promptly after the challenge is created; log error.message for specific Supabase codes."],"exampleFix":"// before\nconst { data: c } = await supabase.auth.mfa.challenge({ factorId });\nawait client.verifyMFA(factorId, code); // may reuse stale challenge internally\n// after\nlet ok = false;\nfor (let attempt = 0; attempt < 3 && !ok; attempt++) {\n  const code = await promptForTotp(); // fresh code each attempt\n  try { await client.verifyMFA(factorId, code); ok = true; }\n  catch (e) { if (e.code !== 'INVALID_MFA_CODE') throw e; }\n}","handlingStrategy":"retry","validationCode":"// guard before submitting\nif (!/^[0-9]{6}$/.test(code)) throw new Error('TOTP code must be 6 digits');\n// prompt immediately after challenge creation so the code is still in its validity window","typeGuard":"function isSixDigitCode(c: unknown): c is string {\n  return typeof c === 'string' && /^[0-9]{6}$/.test(c);\n}","tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try {\n    await client.verifyMFA(factorId, await promptTotp());\n    break;\n  } catch (e) {\n    if (e instanceof AuthenticationError && e.code === 'INVALID_MFA_CODE') {\n      console.error('Incorrect or expired code — try the current 6-digit code');\n      continue; // new prompt (and new challenge)\n    }\n    throw e;\n  }\n}","preventionTips":["Prompt for and submit the code promptly after the challenge is created.","Never reuse a TOTP code or a consumed challenge across attempts.","Ask users to check authenticator device clock sync on repeated failures.","Limit retries (2-3) and surface a clear 'wrong code' message each time."],"tags":["auth","mfa","totp","invalid-input"],"backgroundTag":"invalid-mfa-code","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}