n8n-io/n8n · error · InternalServerError
Email sending must be set up in order to request a password…
Error message
Email sending must be set up in order to request a password reset email
What it means
POST /rest/forgot-password requires SMTP/email to be configured, because the only useful action is sending a reset email. When `mailer.isEmailSetUp` is false, n8n throws InternalServerError (500) — there is no reset path without a mailer.
Solutions
- Configure SMTP via env vars (N8N_SMTP_HOST, N8N_SMTP_PORT, N8N_SMTP_USER, N8N_SMTP_PASS, etc.) and restart n8n.
- Alternatively, have an admin reset the user's password directly via CLI (`n8n user:reset`) or the admin users panel, bypassing email.
Defensive patterns
Strategy: validation
Validate before calling
// Expose mailer.isEmailSetUp via /settings and gate the forgot-password UI.
if (!settings.emailSetUp) {
showNotice('Email is not configured — ask an admin to reset your password.');
return;
}
await restApi.post('/forgot-password', { email }); Prevention
- Hide the forgot-password link in the UI until SMTP is configured.
- On fresh installs, drive the owner through email setup before exposing password reset.
- Provide an admin CLI reset fallback in your runbook.
When it happens
Trigger: POST /rest/forgot-password while the UserManagementMailer reports isEmailSetUp === false (no SMTP/connection test config).
Common situations: Fresh install with no SMTP env vars; owner never completed the email setup screen; SMTP host/port env removed in a redeploy.
Related errors
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/e5a98869111ed591.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/controllers/password-reset.controller.ts:79
@Post('/forgot-password', {
skipAuth: true,
ipRateLimit: { limit: 20, windowMs: 5 * Time.minutes.toMilliseconds },
keyedRateLimit: createBodyKeyedRateLimiter<ForgotPasswordRequestDto>({
limit: 3,
field: 'email',
}),
middlewares: [createJitterMiddleware({ minMs: 200, maxMs: 1000 })],
})
async forgotPassword(
_req: AuthlessRequest,
_res: Response,
@Body payload: ForgotPasswordRequestDto,
) {
if (!this.mailer.isEmailSetUp) {
this.logger.debug(
'Request to send password reset email failed because emailing was not set up',
);
throw new InternalServerError(
'Email sending must be set up in order to request a password reset email',
);
}
try {
const { email } = payload;
// User should just be able to reset password if one is already present
const user = await this.userRepository.findNonShellUser(email);
if (!user) {
this.logger.debug('No user found in the system');
return;
}
if (user.role.slug !== GLOBAL_OWNER_ROLE.slug && !this.license.isWithinUsersLimit()) {
this.logger.debug(
'Request to send password reset email failed because the user limit was reached',
);View on GitHub (pinned to 5ac6606e81)