{"record":{"id":"4c00f1f1abaade1a","repo":"v2rayA/v2rayA","slug":"ports-duplicate-check-it","errorCode":null,"errorMessage":"ports duplicate. check it","messagePattern":"ports duplicate\\. check it","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/server/service/ports.go","lineNumber":42,"sourceCode":"\t}\n\tif ports.Http != 0 {\n\t\tset[ports.Http] = struct{}{}\n\t\tcnt++\n\t}\n\tif ports.Socks5WithPac != 0 {\n\t\tset[ports.Socks5WithPac] = struct{}{}\n\t\tcnt++\n\t}\n\tif ports.HttpWithPac != 0 {\n\t\tset[ports.HttpWithPac] = struct{}{}\n\t\tcnt++\n\t}\n\tif ports.Vmess != 0 {\n\t\tset[ports.Vmess] = struct{}{}\n\t\tcnt++\n\t}\n\tif cnt > len(set) {\n\t\treturn fmt.Errorf(\"ports duplicate. check it\")\n\t}\n\tdetectSyntax := make([]string, 0)\n\tif ports.Socks5 != origin.Socks5 {\n\t\torigin.Socks5 = ports.Socks5\n\t\tif origin.Socks5 != 0 {\n\t\t\tdetectSyntax = append(detectSyntax, strconv.Itoa(origin.Socks5)+\":tcp,udp\")\n\t\t}\n\t}\n\tif ports.Http != origin.Http {\n\t\torigin.Http = ports.Http\n\t\tif origin.Http != 0 {\n\t\t\tdetectSyntax = append(detectSyntax, strconv.Itoa(origin.Http)+\":tcp\")\n\t\t}\n\t}\n\tif ports.Socks5WithPac != origin.Socks5WithPac {\n\t\torigin.Socks5WithPac = ports.Socks5WithPac\n\t\tif origin.Socks5WithPac != 0 {\n\t\t\tdetectSyntax = append(detectSyntax, strconv.Itoa(origin.Socks5WithPac)+\":tcp,udp\")","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/v2rayA/v2rayA/blob/71e5442fc548c05680ee55eae943e6c0afe9ac51/service/server/service/ports.go#L24-L60","documentation":"SetPorts updates global listening port settings (Socks5, Http, Socks2/Http2, Vmess etc.). It inserts every non-zero requested port into a set and, if the count of non-zero ports exceeds the set size, at least two ports are equal and it rejects the change with 'ports duplicate. check it'.","triggerScenarios":"Calling SetPorts (via PutPorts API) with a Ports object where two or more non-zero fields share the same port number, e.g. Socks5 == Http == 1080, or Vmess equals Socks5.","commonSituations":"Frontend form letting users enter the same port twice; clients copying one port into all fields; defaults colliding with a user-entered port.","solutions":["Ensure every non-zero port field in the request has a distinct value","Set unused protocol fields to 0 (0 means disabled and is exempt from the duplicate check)","Check the current origin settings and pick non-conflicting ports"],"exampleFix":"// before\n{\"socks5\":1080,\"http\":1080,\"vmess\":0} // duplicate\n// after\n{\"socks5\":1080,\"http\":8080,\"vmess\":0}","handlingStrategy":"validation","validationCode":"func hasDuplicatePorts(p configure.Ports) bool {\n    set := map[int]struct{}{}\n    cnt := 0\n    for _, v := range []int{p.Socks5, p.Http, p.Socks2, p.Http2, p.Vmess} {\n        if v != 0 {\n            set[v] = struct{}{}\n            cnt++\n        }\n    }\n    return cnt > len(set)\n}\nif hasDuplicatePorts(req.Ports) {\n    return fmt.Errorf(\"ports must be unique (0 disables a listener)\")\n}","typeGuard":null,"tryCatchPattern":"err := service.SetPorts(ports)\nif err != nil && strings.Contains(err.Error(), \"ports duplicate\") {\n    return fmt.Errorf(\"please give each protocol a distinct port\")\n}","preventionTips":["Uniquely assign each protocol its own port","Use 0 for disabled listeners, which is exempt from the check","Compare against current settings before submitting port changes"],"tags":["validation","ports","conflict"],"backgroundTag":"duplicate-port-config","analyzedSha":"71e5442fc548c05680ee55eae943e6c0afe9ac51","analyzedAt":"2026-09-05T20:04:37.459Z","contentChangedAt":"2026-09-05T20:04:37.459Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}