XTLS/Xray-core · error

User ${email} not found.

Error message

User ${email} not found.

What it means

Validator.Del found no user registered under the given (lowercased) email — v.email.Load returned nil. Nothing was deleted; the error tells you the key does not match any current user of this trojan inbound.

Source

Thrown at proxy/trojan/validator.go:38

	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
}

// Get a trojan user with hashed key, nil if user doesn't exist.
func (v *Validator) GetByEmail(email string) *protocol.MemoryUser {
	email = strings.ToLower(email)

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. List the inbound's current users (API/config) and use the email exactly as stored
  2. Make deletion flows tolerate 'not found' as success if idempotency is desired
  3. Check for whitespace/case drift in the email string before calling Del

Example fix

// tolerate double-delete in automation
if err := validator.Del(email); err != nil && !strings.Contains(err.Error(), "not found") {
    return err
}
return nil
Defensive patterns

Strategy: try-catch

Validate before calling

// check existence first
func userExists(v *Validator, email string) bool {
    u, _ := v.email.Load(strings.ToLower(email))
    return u != nil
}

Try / catch

if err := v.Del(email); err != nil {
    if strings.Contains(err.Error(), "not found") {
        return nil // deletion is idempotent
    }
    return err
}

Prevention

When it happens

Trigger: Deleting an email that was never added, was already deleted (double-remove), or differs in more than case (typo, trailing whitespace, domain change).

Common situations: Idempotent-retry scripts hitting 'already removed' users; stale config drift between what operators think is registered and actual state; emails edited on the client side only.

Related errors


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