MHSanaei/3x-ui · warning
password can not be empty
Error message
password can not be empty
What it means
The sibling guard in UpdateFirstUser: the password argument is empty, so the function refuses before hashing. Because UpdateFirstUser always writes BOTH username and password in one Updates() call, an empty password would not be skipped — it would overwrite the admin's password hash with the bcrypt of "", effectively breaking admin auth.
Source
Thrown at internal/web/service/panel/user.go:147
_ = s.settingService.SetTwoFactorEnable(false)
_ = s.settingService.SetTwoFactorToken("")
}
return db.Model(model.User{}).
Where("id = ?", id).
Updates(map[string]any{
"username": username,
"password": hashedPassword,
"login_epoch": gorm.Expr("login_epoch + 1"),
}).
Error
}
func (s *UserService) UpdateFirstUser(username string, password string) error {
if username == "" {
return errors.New("username can not be empty")
} else if password == "" {
return errors.New("password can not be empty")
}
hashedPassword, er := crypto.HashPasswordAsBcrypt(password)
if er != nil {
return er
}
db := database.GetDB()
user := &model.User{}
err := db.Model(model.User{}).First(user).Error
if database.IsNotFound(err) {
user.Username = username
user.Password = hashedPassword
return db.Model(model.User{}).Create(user).Error
} else if err != nil {
return err
}
user.Username = usernameView on GitHub (pinned to ad32144c42)
Solutions
- Always pass the intended password (current or new) whenever this endpoint is used — it updates both fields atomically
- If only the username should change, use the endpoint/flow that updates credentials separately rather than emptying the password
- Validate non-empty password at the form/API layer before the call
Example fix
// before
err := userService.UpdateFirstUser("admin", "")
// after
err := userService.UpdateFirstUser("admin", req.Password)
// with earlier validation: if req.Password == "" { return 400 } Defensive patterns
Strategy: validation
Validate before calling
if password == "" {
return errors.New("password required")
}
err := userService.UpdateFirstUser(username, password) Prevention
- Remember UpdateFirstUser writes username AND password atomically — never call it with one field empty
- Send both fields from the settings form or use a dedicated single-field flow
- Hash-validate on the frontend that both inputs are non-blank before submit
When it happens
Trigger: Calling UpdateFirstUser(username, "") — a settings form where the password input was left blank, or an API client that only intended to rename the user and passed no password.
Common situations: 'Change username only' flows that reuse the update endpoint without re-sending the current password; frontend password field cleared before submit; migration scripts that copy a user with no password set.
Related errors
- username can not be empty
- missing required user field %q
- The new username and password are empty
- ❌ Failed to get inbounds.
- tg_id must be a positive integer
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/560e481e60a53e29.
Report an issue: GitHub.