Billionmail/BillionMail · warning

Login failed too many times, please try again after

Error message

Login failed too many times, please try again after %d seconds

What it means

Login implements rate limiting: after too many failed attempts a cache key stores a release timestamp. When a login is attempted while blocked, the handler returns this error with the remaining seconds until the block expires. The seconds value is releaseTime minus now.

Solutions

  1. Wait the reported number of seconds before retrying
  2. Reset the password via the recovery flow instead of guessing
  3. Clear/invalidate the rate-limit cache key (Redis) if the block is confirmed to be from a shared IP or attacker
  4. Increase blockTime/threshold configuration if too aggressive for legitimate users

Example fix

// before (immediate retry)
await login(user, wrongPassword)
// after (respect the block)
const waitSec = 60; // from error message
await new Promise(r => setTimeout(r, waitSec * 1000));
await login(user, password)
Defensive patterns

Strategy: try-catch

Validate before calling

// track local failure count and back off before hitting the limit
if (++localFailures >= 4) await sleep(backoffMs);

Try / catch

try {
  await api.login(creds);
} catch (err) {
  const m = String(err.message).match(/try again after (\d+) seconds/);
  if (m) await sleep(parseInt(m[1], 10) * 1000 + 500); // retry after block expires
  else throw err;
}

Prevention

When it happens

Trigger: Repeated failed login attempts (wrong password) exceeding the configured threshold; a user retrying rapidly while already blocked; automated scripts/bots hammering the login endpoint; a stale cache entry from earlier failures still counting against the user.

Common situations: User forgets password and keeps guessing; CI/monitoring scripts using outdated credentials; shared IPs (office NAT) where multiple users' failures accumulate on one key; password manager with stale credentials auto-submitting.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/78c812a2adafb90c. Report an issue: GitHub.

Appendix: source

Thrown at core/internal/controller/rbac/rbac_v1_auth.go:60

		// Login success
		if loginSuccessFlag {
			public.RemoveCache(cacheKey)
			return
		}

		// Increment login retries
		public.SetCache(cacheKey, loginRetries+1, 300)
	}()

	if loginRetries >= maxRetries {
		k := "USER_LOGIN_RETRIES_RELEASE_TIME:" + clientIp
		releaseTime, blocked := public.GetCache(k).(int64)
		if !blocked {
			releaseTime = time.Now().Unix() + int64(blockTime)
			public.SetCache(k, releaseTime, blockTime)
		}

		err = fmt.Errorf("Login failed too many times, please try again after %d seconds", releaseTime-time.Now().Unix())
		return
	}

	// Check if validation code is required
	if mustValidateCode {
		validateSuccess = false

		if req.ValidateCodeId == "" || req.ValidateCode == "" {
			err = fmt.Errorf("Validation code ID and code cannot be empty")
			return
		}

		if !service.VerifyCaptcha(req.ValidateCodeId, req.ValidateCode) {
			err = fmt.Errorf("Invalid validation code")
			return
		}

		validateSuccess = true

View on GitHub (pinned to fc36c76c05)