n8n-io/n8n · error · BadRequestError
MFA secret could not be verified
Error message
MFA secret could not be verified
What it means
POST /rest/mfa/verify: the supplied code failed TOTP verification against the stored secret (`totp.verifySecret` returned false, no window slack). Indicates a wrong or expired code rather than a missing secret or missing code.
Source
Thrown at packages/cli/src/controllers/mfa.controller.ts:216
}
@Post('/verify', {
allowSkipMFA: true,
keyedRateLimit: createUserKeyedRateLimiter({}),
})
async verifyMFA(req: MFA.Verify) {
const { id } = req.user;
const { mfaCode } = req.body;
const { decryptedSecret: secret } = await this.mfaService.getSecretAndRecoveryCodes(id);
if (!mfaCode) throw new BadRequestError('MFA code is required to enable MFA feature');
if (!secret) throw new BadRequestError('No MFA secret se for this user');
const verified = this.mfaService.totp.verifySecret({ secret, mfaCode });
if (!verified) throw new BadRequestError('MFA secret could not be verified');
}
}
View on GitHub (pinned to 5ac6606e81)
Solutions
- Enter a freshly generated code immediately before submitting.
- Sync the device clock (TOTP is time-sensitive).
- If persistent, re-enroll: disable/QR/enable flow to reseed the authenticator.
Defensive patterns
Strategy: try-catch
Validate before calling
// Shape-only; validity is determined server-side.
if (!/^\d{6}$/.test(mfaCode)) throw new Error('Enter a 6-digit code.'); Try / catch
try {
await restApi.post('/mfa/verify', { mfaCode });
} catch (e) {
if (/could not be verified/i.test(e.response?.data?.message)) {
promptFreshCode('Code rejected — enter a fresh one.');
} else throw e;
} Prevention
- Submit immediately after the user enters the code (TOTP is time-boxed).
- Sync the device clock if verification keeps failing across endpoints.
- Offer a re-enroll path if the user's authenticator is permanently out of sync.
When it happens
Trigger: POST /rest/mfa/verify with a non-empty mfaCode that does not match the current TOTP value for the user's secret.
Common situations: Typo in the 6 digits, code expired between typing and submit, device clock drift, wrong authenticator entry.
Related errors
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/f14b22558260f82b.
Report an issue: GitHub.