XTLS/Xray-core · error
failed to parse HTTP user
Error message
failed to parse HTTP user
What it means
Thrown when json.Unmarshal of a raw entry from httpSettings.servers[].users into protocol.User fails. Each users element is a JSON object whose fields (id/email/level in protocol.User terms) must deserialize cleanly; a type mismatch (e.g. level as a string) or malformed JSON surfaces here with the parse error as the base cause and AtError severity. Only hit on the servers[].users form, not the legacy top-level username form.
Source
Thrown at infra/conf/http.go:100
if len(v.Servers) != 1 {
return nil, errors.New(`HTTP settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple HTTP outbounds and routing balancer instead`)
}
for _, serverConfig := range v.Servers {
if len(serverConfig.Users) > 1 {
return nil, errors.New(`HTTP servers: "users" should have one member at most. Multiple members in "users" should use multiple HTTP outbounds and routing balancer instead`)
}
server := &protocol.ServerEndpoint{
Address: serverConfig.Address.Build(),
Port: uint32(serverConfig.Port),
}
for _, rawUser := range serverConfig.Users {
user := new(protocol.User)
if v.Address != nil {
user.Level = v.Level
user.Email = v.Email
} else {
if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New("failed to parse HTTP user").Base(err).AtError()
}
}
account := new(HTTPAccount)
if v.Address != nil {
account.Username = v.Username
account.Password = v.Password
} else {
if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New("failed to parse HTTP account").Base(err).AtError()
}
}
user.Account = serial.ToTypedMessage(account.Build())
server.User = user
break
}
config.Server = server
break
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Make each users element a valid JSON object with correctly typed fields (e.g. level as number)
- Pre-validate the outbound JSON with a linter or jq before feeding it to Xray
- Read the chained base error to find the exact JSON offset/field that failed
Example fix
// before
"users": [ { "user": "a", "level": "0" } ]
// after
"users": [ { "user": "a", "level": 0 } ] Defensive patterns
Strategy: validation
Validate before calling
// Validate each users entry unmarshals into protocol.User cleanly
var probe protocol.User
if err := json.Unmarshal(rawUser, &probe); err != nil {
return fmt.Errorf("users entry invalid: %w", err)
} Try / catch
// Go: catch and enrich
if err := outboundConf.Build(); err != nil {
if strings.Contains(err.Error(), "failed to parse HTTP user") {
log.Printf("config file: users[%d] has wrong field types", i)
}
return err
} Prevention
- Keep level as a JSON number and email/id as strings
- jq-validate the generated config before feeding it to Xray
When it happens
Trigger: A users entry like {"level": "0"} (string where uint32 expected), an array element that is not an object, or invalid JSON syntax inside the users array.
Common situations: Hand-editing JSON and quoting numeric fields; config templating engines rendering booleans or nulls into user objects.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse HTTP account
- failed to decode config:
- illegal ip rule:
- illegal domain rule:
- unknown format of a string list:
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/5ef4a5b22b01fbb2.
Report an issue: GitHub.