XTLS/Xray-core · error
user account is not valid
Error message
user account is not valid
What it means
Thrown by the trojan client when the configured server user's Account is not a *MemoryAccount (the trojan protocol's internal account type holding the key). This is a programming/registration error: the user object attached to the server spec was built with a different account type than trojan's protocol.RegisterAccount produces.
Source
Thrown at proxy/trojan/client.go:81
rawConn, err := dialer.Dial(ctx, server.Destination)
if err != nil {
return err
}
conn = rawConn
return nil
})
if err != nil {
return errors.New("failed to find an available destination").AtWarning().Base(err)
}
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", server.Destination.NetAddr())
defer conn.Close()
user := server.User
account, ok := user.Account.(*MemoryAccount)
if !ok {
return errors.New("user account is not valid")
}
var newCtx context.Context
var newCancel context.CancelFunc
if session.TimeoutOnlyFromContext(ctx) {
newCtx, newCancel = context.WithCancel(context.Background())
}
sessionPolicy := c.policyManager.ForLevel(user.Level)
ctx, cancel := context.WithCancel(ctx)
timer := signal.CancelAfterInactivity(ctx, func() {
cancel()
if newCancel != nil {
newCancel()
}
}, sessionPolicy.Timeouts.ConnectionIdle)
postRequest := func() error {View on GitHub (pinned to 7d214f8b09)
Solutions
- Construct trojan users through the documented path so accounts are parsed via trojan's account registration (config user -> protocol.MemoryAccount with Key derived from password).
- If maintaining a fork, keep the type-assert target in sync with the registered account type.
- Regenerate the server spec from protobuf (NewServerSpecFromPB) instead of hand-building user objects.
Defensive patterns
Strategy: type-guard
Type guard
func isTrojanMemoryAccount(a interface{}) bool {
_, ok := a.(*trojan.MemoryAccount)
return ok
} Prevention
- Always build users via protocol registration paths, never by hand.
- In forks, keep account type assertions next to their registration in one package.
- Add a compile-time var _ = ... assertion tying the client to the account type.
When it happens
Trigger: server.User.Account type-asserts to *MemoryAccount and fails — e.g. a custom builder inserted a *protocol.AccountUser or a nil/default account, or a fork changed the account type without updating this client.
Common situations: Vendored fork of xray-core where account types were refactored; embedding code constructing ServerSpec users manually with the wrong account implementation; version skew between core and a custom trojan handler.
Related errors
- Upstream sent malformed statistics.
- target not specified
- can't get inbound proxy from handler.
- proxy is not a UserManager
- not an inbound operation
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/5c4afd0267e7b9e4.
Report an issue: GitHub.