RocketChat/Rocket.Chat · error · Meteor.Error

error-login-blocked-for-ip

error-login-blocked-for-ip

Error message

Login has been temporarily blocked For IP

What it means

validateLoginAttemptAsync -> isValidLoginAttemptByIp rejects the login when brute-force protection by IP is active: Block_Multiple_Failed_Logins_Enabled and Block_Multiple_Failed_Logins_By_Ip are on, the client IP is not in Block_Multiple_Failed_Logins_Ip_Whitelist, and failed attempts recorded in ServerEvents from that IP within Block_Multiple_Failed_Logins_Time_To_Unblock_By_Ip_In_Minutes reach Block_Multiple_Failed_Logins_Attempts_Until_Block_By_Ip. A successful login from the IP resets the counter.

Source

Thrown at apps/meteor/server/lib/auth/startup.js:413

			}
		}
	}

	if (!options.skipAppsEngineEvent) {
		// `post` triggered events don't need to wait for the promise to resolve
		Apps.self?.triggerEvent(AppEvents.IPostUserCreated, { user, performedBy: options.performedBy }).catch((e) => {
			Apps.self?.getRocketChatLogger().error({ msg: 'Error while executing post user created event', err: e });
		});
	}

	return _id;
};

const validateLoginAttemptAsync = async function (login) {
	login = await callbacks.run('beforeValidateLogin', login);

	if (!(await isValidLoginAttemptByIp(getClientAddress(login.connection)))) {
		throw new Meteor.Error('error-login-blocked-for-ip', 'Login has been temporarily blocked For IP', {
			function: 'Accounts.validateLoginAttempt',
		});
	}

	if (!(await isValidAttemptByUser(login))) {
		throw new Meteor.Error('error-login-blocked-for-user', 'Login has been temporarily blocked For User', {
			function: 'Accounts.validateLoginAttempt',
		});
	}

	if (login.allowed !== true) {
		return login.allowed;
	}

	if (login.user.type === 'visitor') {
		return true;
	}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Wait out Block_Multiple_Failed_Logins_Time_To_Unblock_By_Ip_In_Minutes, then log in once successfully to reset the counter
  2. Add the affected IP to Block_Multiple_Failed_Logins_Ip_Whitelist (comma-separated)
  3. Fix proxy headers so getClientAddress resolves the real client IP instead of the shared proxy address
  4. Tune Block_Multiple_Failed_Logins_Attempts_Until_Block_By_Ip / window, or disable Block_Multiple_Failed_Logins_By_Ip if NAT makes IP blocking impractical
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await loginWithPassword(user, password);
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-login-blocked-for-ip') {
    // stop retrying; surface 'too many attempts from your network, try later'
    // schedule the next attempt after Block_Multiple_Failed_Logins_Time_To_Unblock_By_Ip_In_Minutes
  }
  throw e;
}

Prevention

When it happens

Trigger: Password logins (LoginWithPassword / POST /api/v1/login) from an IP that reached the failed-attempt threshold inside the unblock window — brute-force attempts, several users behind one NAT address, or a reverse proxy that reports the same IP for every client.

Common situations: A whole office behind NAT gets locked out after a few users mistype passwords; reverse proxy not forwarding X-Forwarded-For so getClientAddress sees only the proxy IP; password spraying from one IP; long Time_To_Unblock windows making blocks linger.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/4eae468dca9d5ba1. Report an issue: GitHub.