AdguardTeam/AdGuardHome · warning

login attempt blocked for

Error message

login attempt blocked for %s

What it means

Basic-auth attempt rejected because the source IP is currently blocked by the login rate limiter; the message includes how long the block remains. The deferred handler also counts this failed attempt.

Solutions

  1. Correct the Basic Auth credentials being used
  2. Wait for the block window to expire before retrying
  3. Add exponential backoff / stop-on-401 in automated clients
  4. Use a distinct source IP or trusted-proxy config where applicable

Example fix

// before
resp = basic_auth(user, wrong_pass)
# retry immediately on failure
// after
if resp.status_code == 401 and 'blocked for' in resp.text:
    time.sleep(parse_duration(resp.text))
Defensive patterns

Strategy: retry

Try / catch

// Parse remaining block duration from error and sleep before retry
if strings.Contains(err.Error(), "blocked for") {
    d := parseDurationFromMsg(err.Error())
    time.Sleep(d)
}

Prevention

When it happens

Trigger: HTTP Basic Auth requests from an IP that exceeded failed-login limits; rateLimiter.check(remoteIP) returns a positive remaining duration.

Common situations: Monitoring scripts or API clients using Basic Auth with wrong credentials repeatedly; shared NAT IP accumulating failures; retry loops without backoff.

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/d632bad9a2dcbeae. Report an issue: GitHub.

Appendix: source

Thrown at internal/home/authhttp.go:583

	r *http.Request,
) (user *aghuser.User, err error) {
	login, pass, ok := r.BasicAuth()
	if !ok {
		return nil, nil
	}

	var remoteIP string
	// The real IP address of the client [realIP] cannot be used here without
	// taking trusted proxies into account due to security issues:
	//
	// See https://github.com/AdguardTeam/AdGuardHome/issues/2799.
	if remoteIP, err = netutil.SplitHost(r.RemoteAddr); err != nil {
		return nil, fmt.Errorf("getting remote address: %w", err)
	}

	rateLimiter := mw.rateLimiter
	if left := rateLimiter.check(remoteIP); left > 0 {
		return nil, fmt.Errorf("login attempt blocked for %s", left)
	}

	defer func() {
		if err != nil {
			rateLimiter.inc(remoteIP)

			return
		}

		rateLimiter.remove(remoteIP)
	}()

	user, _ = mw.users.ByLogin(ctx, aghuser.Login(login))
	if user == nil {
		return nil, errInvalidLogin
	}

	ok = user.Password.Authenticate(ctx, pass)

View on GitHub (pinned to b41aefbe51)