{"record":{"id":"916e7f9e020d4eea","repo":"XTLS/Xray-core","slug":"vmess-settings-vnext-should-have-one-and-only-o","errorCode":null,"errorMessage":"VMess settings: \"vnext\" should have one and only one member. Multiple endpoints in \"vnext\" should use multiple VMess outbounds and routing balancer instead","messagePattern":"VMess settings: \"vnext\" should have one and only one member\\. Multiple endpoints in \"vnext\" should use multiple VMess outbounds and routing balancer instead","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/vmess.go","lineNumber":137,"sourceCode":"\tReceivers   []*VMessOutboundTarget `json:\"vnext\"`\n}\n\n// Build implements Buildable\nfunc (c *VMessOutboundConfig) Build() (proto.Message, error) {\n\terrors.PrintNonRemovalDeprecatedFeatureWarning(\"VMess (with no Forward Secrecy, etc.)\", \"VLESS Encryption\")\n\n\tconfig := new(outbound.Config)\n\tif c.Address != nil {\n\t\tc.Receivers = []*VMessOutboundTarget{\n\t\t\t{\n\t\t\t\tAddress: c.Address,\n\t\t\t\tPort:    c.Port,\n\t\t\t\tUsers:   []json.RawMessage{{}},\n\t\t\t},\n\t\t}\n\t}\n\tif len(c.Receivers) != 1 {\n\t\treturn nil, errors.New(`VMess settings: \"vnext\" should have one and only one member. Multiple endpoints in \"vnext\" should use multiple VMess outbounds and routing balancer instead`)\n\t}\n\tfor _, rec := range c.Receivers {\n\t\tif len(rec.Users) != 1 {\n\t\t\treturn nil, errors.New(`VMess vnext: \"users\" should have one and only one member. Multiple members in \"users\" should use multiple VMess outbounds and routing balancer instead`)\n\t\t}\n\t\tif rec.Address == nil {\n\t\t\treturn nil, errors.New(`VMess vnext: \"address\" is not set`)\n\t\t}\n\t\tspec := &protocol.ServerEndpoint{\n\t\t\tAddress: rec.Address.Build(),\n\t\t\tPort:    uint32(rec.Port),\n\t\t}\n\t\tfor _, rawUser := range rec.Users {\n\t\t\tuser := new(protocol.User)\n\t\t\tif c.Address != nil {\n\t\t\t\tuser.Level = c.Level\n\t\t\t\tuser.Email = c.Email\n\t\t\t} else {","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/vmess.go#L119-L155","documentation":"Thrown by VMessOutboundConfig.Build() when the \"vnext\" (internally Receivers) array of a full-style VMess outbound does not hold exactly one endpoint. One outbound targets one server; failover/load-balancing across servers is expressed as multiple VMess outbounds plus a routing balancer. The simplified style (top-level \"address\") auto-synthesizes a single receiver, so only full-style configs with 0 or 2+ entries hit this.","triggerScenarios":"\"settings\":{\"vnext\":[{...},{...}]} with two servers; \"vnext\":[] or the key omitted entirely in full style; leftover multi-vnext configs from old V2Ray 3.x.","commonSituations":"Legacy failover configs predating the balancer requirement; merging two outbounds 'for tidiness'; templates that ship an empty vnext placeholder.","solutions":["Reduce vnext to exactly one object per outbound","Model multiple servers as multiple tagged outbounds plus a routing balancer with a strategy (e.g. leastPing)","Or switch to simplified style: \"address\"/\"port\"/\"id\" at the outbound settings top level"],"exampleFix":"// before\n\"settings\": { \"vnext\": [ {\"address\":\"a.com\",\"port\":443,\"users\":[...]}, {\"address\":\"b.com\",\"port\":443,\"users\":[...]} ] }\n// after\n\"outbounds\": [\n  { \"protocol\": \"vmess\", \"settings\": { \"vnext\": [ {\"address\":\"a.com\",\"port\":443,\"users\":[...]} ] }, \"tag\": \"vm-a\" },\n  { \"protocol\": \"vmess\", \"settings\": { \"vnext\": [ {\"address\":\"b.com\",\"port\":443,\"users\":[...]} ] }, \"tag\": \"vm-b\" }\n]\n// plus routing.balancers over [\"vm-a\",\"vm-b\"]","handlingStrategy":"validation","validationCode":"func validateSingleVMessVnext(cfg map[string]any) error {\n\toutbounds, _ := cfg[\"outbounds\"].([]any)\n\tfor _, ob := range outbounds {\n\t\tm, _ := ob.(map[string]any)\n\t\tif p, _ := m[\"protocol\"].(string); p != \"vmess\" { continue }\n\t\tsettings, _ := m[\"settings\"].(map[string]any)\n\t\tif _, simplified := settings[\"address\"]; simplified { continue }\n\t\tvnext, _ := settings[\"vnext\"].([]any)\n\t\tif len(vnext) != 1 {\n\t\t\treturn fmt.Errorf(\"outbound %v: vmess vnext must have exactly 1 entry, got %d\", m[\"tag\"], len(vnext))\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":"func vmessSingleVnext(settings map[string]any) bool {\n\tif _, ok := settings[\"address\"]; ok { return true }\n\tv, ok := settings[\"vnext\"].([]any)\n\treturn ok && len(v) == 1\n}","tryCatchPattern":null,"preventionTips":["One VMess outbound per server; use routing balancers for multiple servers","Prefer the simplified outbound style to avoid vnext arrays entirely","Migrate any pre-balancer-era configs with multiple vnext entries before upgrading"],"tags":["vmess","outbound","vnext","balancer","config","validation","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}