bytebase/bytebase · error
password was reset, but failed to clear the login attempt co
Error message
password was reset, but failed to clear the login attempt counter
What it means
After (optionally) changing the password, ResetUserPassword clears the user's failed-login counter via store.ClearLoginAttempt so an existing lockout does not keep Login returning ResourceExhausted with the new password. If that clear fails AND the password was actually changed (result.Changed=true), the result is returned together with this error: the reset succeeded but the lockout persists.
Source
Thrown at backend/component/recovery/service.go:377
result := &ResetUserPasswordResult{WorkspaceID: request.WorkspaceID, Email: email}
if bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), request.Password) != nil {
passwordHash, err := bcrypt.GenerateFromPassword(request.Password, bcrypt.DefaultCost)
if err != nil {
return nil, errors.Wrap(err, "failed to hash user password")
}
if _, err := s.store.UpdateUser(ctx, user, &store.UpdateUserMessage{PasswordHash: new(string(passwordHash))}); err != nil {
return nil, errors.Wrap(err, "failed to reset user password")
}
result.Changed = true
}
// A lockout the user guessed themselves into must not outlive the reset:
// without this, the operator hands over a password that Login keeps
// refusing with ResourceExhausted until the window lapses.
if err := s.store.ClearLoginAttempt(ctx, email, storepb.LoginAttemptKind_PASSWORD); err != nil {
if result.Changed {
return result, errors.Wrap(err, "password was reset, but failed to clear the login attempt counter")
}
return result, errors.Wrap(err, "failed to clear the login attempt counter")
}
if err := s.createAuditLog(ctx, request.WorkspaceID, resetUserPasswordAuditMethod, string(auditRequest)); err != nil {
return result, errors.Wrap(err, "user password reset completed, but failed to create the recovery audit log")
}
return result, nil
}
func (s *Service) getActiveEndUser(ctx context.Context, email string) (*store.UserMessage, error) {
account, err := s.store.GetAccountByEmail(ctx, email)
if err != nil {
return nil, errors.Wrap(err, "failed to find user identity")
}
if account == nil {
return nil, errors.Errorf("user %q does not exist", email)
}View on GitHub (pinned to 1870550677)
Solutions
- Inspect the wrapped inner error and retry ResetUserPassword — it is safe because the bcrypt compare makes the second run a no-op for the password, and it will re-attempt ClearLoginAttempt.
- Manually clear the login-attempt record for the email (PASSWORD kind) if the API keeps retry-failing.
- Verify the login-attempt table exists and is writable (migrations, privileges).
- Inform the operator that the new password may still be refused with ResourceExhausted until the lockout window lapses if the counter cannot be cleared.
Example fix
// before
res, err := svc.ResetUserPassword(ctx, req)
if err != nil { return err } // password changed but lockout still active
// after
res, err := svc.ResetUserPassword(ctx, req)
if err != nil {
if res != nil && res.Changed {
// password WAS reset; retry just the counter clear / inform operator
log.Printf("password reset ok, clearing lockout failed: %v", err)
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
// check DB writability of both user and login-attempt storage first
if err := store.Ping(ctx); err != nil {
return fmt.Errorf("metadata DB unstable, partial reset likely: %w", err)
} Try / catch
res, err := svc.ResetUserPassword(ctx, req)
if err != nil {
if res != nil && res.Changed {
// password was reset; lockout may persist — retry to clear the counter
res, err = svc.ResetUserPassword(ctx, req)
}
if err != nil { return err }
} Prevention
- Retry the whole call on this error; bcrypt compare makes the re-run safe
- Verify login-attempt storage is migrated and writable
- Watch for ResourceExhausted on Login after resets to detect lingering lockouts
When it happens
Trigger: Calling ResetUserPassword for a user whose password was updated when ClearLoginAttempt fails: DB write failure on the login-attempt table, connection drop between UpdateUser and ClearLoginAttempt, or a missing login-attempt table/index from incomplete migrations.
Common situations: User was locked out from repeated wrong passwords and the operator resets them during a DB instability; partial migration left the login-attempt storage inconsistent; transient network failure between the two store calls.
Related errors
- failed to clear the login attempt counter
- user password reset completed, but failed to create the reco
- Google Cloud Translation API Error: ${data.error?.message ||
- The plan was created, but its Draft Review Issue was not cre
- Internal
AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06).
Data as JSON: /api/errors/018a99af37d39781.
Report an issue: GitHub.