XTLS/Xray-core · error

HTTP servers: "users" should have one member at most. Multip

Error message

HTTP servers: "users" should have one member at most. Multiple members in "users" should use multiple HTTP outbounds and routing balancer instead

What it means

Thrown by the HTTP outbound builder when a server entry's users array has more than one member. Each HTTP outbound authenticates with at most one credential pair; multiple credentials require multiple HTTP outbounds and a routing balancer. An empty users array is allowed (no auth).

Source

Thrown at infra/conf/http.go:87

func (v *HTTPClientConfig) Build() (proto.Message, error) {
	config := new(http.ClientConfig)
	if v.Address != nil {
		v.Servers = []*HTTPRemoteConfig{
			{
				Address: v.Address,
				Port:    v.Port,
			},
		}
		if len(v.Username) > 0 {
			v.Servers[0].Users = []json.RawMessage{{}}
		}
	}
	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

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Keep users to zero or one entry per server
  2. Move each credential to its own HTTP outbound and use a routing balancer to distribute traffic

Example fix

// before
"users": [ {"user":"a","pass":"x"}, {"user":"b","pass":"y"} ]
// after
"users": [ {"user":"a","pass":"x"} ]  // second credential in a separate HTTP outbound
Defensive patterns

Strategy: validation

Validate before calling

for _, s := range httpSettings.Servers {
	if len(s.Users) > 1 {
		return fmt.Errorf("server %v has %d users; max is 1", s.Address, len(s.Users))
	}
}

Prevention

When it happens

Trigger: Putting two or more user objects inside httpSettings.servers[0].users; mixing the legacy username/password fields with an extra users entry is safe (legacy path synthesizes exactly one user), but explicit users arrays with 2+ entries fail.

Common situations: Users trying to encode failover credentials for several upstream proxies in one outbound; generated configs that emit a users list unconditionally.

Related errors


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