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 nil

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Pass the exact non-empty email the user was added with (case-insensitive on lookup)
  2. Validate the email field is present before calling the remove API/handler
  3. 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

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


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/ba1572046bfe643f. Report an issue: GitHub.