XTLS/Xray-core · error
VLESS users: invalid user
Error message
VLESS users: invalid user
What it means
Thrown inside the per-client loop of a VLESS inbound when a raw user JSON object fails to unmarshal into protocol.User (the generic user record with email/level). This almost always means the clients entry is not a JSON object with compatible fields — wrong type for email/level, or the entry itself is a string/array.
Source
Thrown at infra/conf/vless.go:59
// Build implements Buildable
func (c *VLessInboundConfig) Build() (proto.Message, error) {
config := new(inbound.Config)
if c.Clients != nil {
c.Users = c.Clients
}
config.Users = make([]*protocol.User, len(c.Users))
switch c.Flow {
case vless.XRV, "":
default:
return nil, errors.New(`VLESS "settings.flow" doesn't support "` + c.Flow + `" in this version`)
}
processClient := func(idx int) error {
rawUser := c.Users[idx]
user := new(protocol.User)
if err := json.Unmarshal(rawUser, user); err != nil {
return errors.New(`VLESS users: invalid user`).Base(err)
}
account := new(vless.Account)
if err := json.Unmarshal(rawUser, account); err != nil {
return errors.New(`VLESS users: invalid user`).Base(err)
}
u, err := uuid.ParseString(account.Id)
if err != nil {
return err
}
account.Id = u.String()
switch account.Flow {
case "":
account.Flow = c.Flow
case vless.XRV:
default:
return errors.New(`VLESS users: "flow" doesn't support "` + account.Flow + `" in this version`)View on GitHub (pinned to 7d214f8b09)
Solutions
- Make each clients entry an object: { "id": "<uuid>", "email": "optional", "level": 0 }
- Keep level as a JSON number and email as a string
- Read the wrapped base error — it names the exact offending field
Example fix
// before
"clients": [ "8c1f4b1a-..." ]
// after
"clients": [ { "id": "8c1f4b1a-...", "level": 0 } ] Defensive patterns
Strategy: validation
Validate before calling
// each clients entry must be an object with string email and numeric level (both optional)
for _, c := range clients {
if !gjson.Valid(c.Raw) || c.Type != gjson.JSON {
return errors.New("each vless client must be a JSON object")
}
if e := gjson.Get(c.Raw, "email"); e.Exists() && e.Type != gjson.String {
return errors.New("client email must be a string")
}
if l := gjson.Get(c.Raw, "level"); l.Exists() && l.Type != gjson.Number {
return errors.New("client level must be a number")
}
} Prevention
- Never put bare UUID strings in clients; always wrap in objects
- Check the wrapped base error message for the exact field at fault
When it happens
Trigger: A "clients" entry like { "id": "...", "level": "high" } (level must be a number) or "clients": ["uuid-string"] (bare string instead of object). The error is wrapped as 'VLESS users: invalid user' with the underlying JSON error attached.
Common situations: Pasting a bare UUID list instead of client objects, or quoting numeric fields during YAML→JSON conversion.
Related errors
- VLESS vnext: "users" should have one and only one member. Mu
- unknown format of a string list:
- invalid address:
- Invalid integer range, expected either string of form "1-2"
- invalid fakedns config
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/3bc868449793cab2.
Report an issue: GitHub.