XTLS/Xray-core · error
Email must not be empty.
Error message
Email must not be empty.
What it means
Validator.Del was called with an empty email string. Deletion looks users up by email key, so an empty key cannot identify any user and is rejected outright rather than silently doing nothing.
Source
Thrown at proxy/trojan/validator.go:33
users sync.Map
}
// Add a trojan user, Email must be empty or unique.
func (v *Validator) Add(u *protocol.MemoryUser) error {
if u.Email != "" {
_, loaded := v.email.LoadOrStore(strings.ToLower(u.Email), u)
if loaded {
return errors.New("User ", u.Email, " already exists.")
}
}
v.users.Store(hexString(u.Account.(*MemoryAccount).Key), u)
return nil
}
// Del a trojan user with a non-empty Email.
func (v *Validator) Del(e string) error {
if e == "" {
return errors.New("Email must not be empty.")
}
le := strings.ToLower(e)
u, _ := v.email.Load(le)
if u == nil {
return errors.New("User ", e, " not found.")
}
v.email.Delete(le)
v.users.Delete(hexString(u.(*protocol.MemoryUser).Account.(*MemoryAccount).Key))
return nil
}
// Get a trojan user with hashed key, nil if user doesn't exist.
func (v *Validator) Get(hash string) *protocol.MemoryUser {
u, _ := v.users.Load(hash)
if u != nil {
return u.(*protocol.MemoryUser)
}
return nilView on GitHub (pinned to 7d214f8b09)
Solutions
- Pass the exact non-empty email the user was added with (case-insensitive on lookup)
- Validate the email field is present before calling the remove API/handler
- If the target user has no email, add one first or remove/rebuild the inbound
Example fix
// before removeUser(inboundTag, "") // after removeUser(inboundTag, "user@x")
Defensive patterns
Strategy: validation
Validate before calling
// guard the management call
func delUser(v *Validator, email string) error {
if strings.TrimSpace(email) == "" {
return errors.New("refusing to delete: email is empty")
}
return v.Del(email)
} Prevention
- Validate required fields at the API edge before they reach Validator.Del
- Use typed request structs so a missing email fails decoding instead of silently passing ""
- Reject blank emails in provisioning tooling early, with a clear message
When it happens
Trigger: Management API 'remove trojan user' style handlers invoked with an omitted/blank email field; config tooling that maps a missing email to "" and still calls Del.
Common situations: Automation scripts deleting by password instead of email; JSON payload with a typo'd field name so email decodes as empty.
Related errors
- User ${email} not found.
- User ${email} already exists.
- proxy is not a UserManager
- failed to parse user
- Counter %s already registered.
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/ba1572046bfe643f.
Report an issue: GitHub.