{"record":{"id":"29ba7e7d82b555d6","repo":"XTLS/Xray-core","slug":"failed-to-parse-socks-user","errorCode":null,"errorMessage":"failed to parse Socks user","messagePattern":"failed to parse Socks user","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/socks.go","lineNumber":118,"sourceCode":"\tif len(v.Servers) != 1 {\n\t\treturn nil, errors.New(`SOCKS settings: \"servers\" should have one and only one member. Multiple endpoints in \"servers\" should use multiple SOCKS outbounds and routing balancer instead`)\n\t}\n\tfor _, serverConfig := range v.Servers {\n\t\tif len(serverConfig.Users) > 1 {\n\t\t\treturn nil, errors.New(`SOCKS servers: \"users\" should have one member at most. Multiple members in \"users\" should use multiple SOCKS outbounds and routing balancer instead`)\n\t\t}\n\t\tserver := &protocol.ServerEndpoint{\n\t\t\tAddress: serverConfig.Address.Build(),\n\t\t\tPort:    uint32(serverConfig.Port),\n\t\t}\n\t\tfor _, rawUser := range serverConfig.Users {\n\t\t\tuser := new(protocol.User)\n\t\t\tif v.Address != nil {\n\t\t\t\tuser.Level = v.Level\n\t\t\t\tuser.Email = v.Email\n\t\t\t} else {\n\t\t\t\tif err := json.Unmarshal(rawUser, user); err != nil {\n\t\t\t\t\treturn nil, errors.New(\"failed to parse Socks user\").Base(err).AtError()\n\t\t\t\t}\n\t\t\t}\n\t\t\taccount := new(SocksAccount)\n\t\t\tif v.Address != nil {\n\t\t\t\taccount.Username = v.Username\n\t\t\t\taccount.Password = v.Password\n\t\t\t} else {\n\t\t\t\tif err := json.Unmarshal(rawUser, account); err != nil {\n\t\t\t\t\treturn nil, errors.New(\"failed to parse socks account\").Base(err).AtError()\n\t\t\t\t}\n\t\t\t}\n\t\t\tuser.Account = serial.ToTypedMessage(account.Build())\n\t\t\tserver.User = user\n\t\t\tbreak\n\t\t}\n\t\tconfig.Server = server\n\t\tbreak\n\t}","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/socks.go#L100-L136","documentation":"While building a SOCKS outbound, Xray unmarshals each raw JSON user object into protocol.User (infra/conf/socks.go:117-118). Any JSON shape that cannot decode into that protobuf-generated struct aborts config load with \"failed to parse Socks user\" wrapping the JSON error. The user object must be a flat object with valid field types (e.g. \"level\": number, \"email\": string).","triggerScenarios":"Only in the \"servers\" form (legacy address/port form skips unmarshal). A users[i] entry that is not an object (a string, number, array), or that contains type mismatches such as \"level\":\"3\" (string instead of number) or \"email\":123. Unknown keys are ignored; wrong value types are not.","commonSituations":"Quoting numbers in generated configs; pasting user entries copied from inbound \"accounts\" sections whose schema differs; trailing commas or comments breaking JSON; passing an array of strings instead of objects.","solutions":["Make each users[i] a JSON object: {\"user\":\"name\",\"pass\":\"pw\",\"level\":0,\"email\":\"opt\"}","Ensure level is an unquoted integer and email is a string; remove non-schema keys with wrong types","Validate the whole config parses as strict JSON before feeding Xray (xray run -test or a JSON linter)"],"exampleFix":"// before\n\"users\": [ { \"user\": \"a\", \"level\": \"3\" } ]\n// after\n\"users\": [ { \"user\": \"a\", \"level\": 3 } ]","handlingStrategy":"validation","validationCode":"for (const u of server.users ?? []) {\n  if (typeof u !== 'object' || u === null || Array.isArray(u)) throw new Error('user entry must be an object');\n  if ('level' in u && !Number.isInteger(u.level)) throw new Error('level must be an integer');\n  if ('email' in u && typeof u.email !== 'string') throw new Error('email must be a string');\n}","typeGuard":"const isUserObject = (u: unknown): u is {user?:string; pass?:string; level?:number; email?:string} =>\n  typeof u === 'object' && u !== null && !Array.isArray(u) &&\n  (!('level' in u) || typeof (u as any).level === 'number') &&\n  (!('email' in u) || typeof (u as any).email === 'string');","tryCatchPattern":"catch (e) { if (e.message.includes('failed to parse Socks user')) { /* surface e.cause: json field/type mismatch in users[] entry */ } }","preventionTips":["Run configs through JSON.parse before handing to Xray","Keep user entries minimal: user, pass, level, email only","Quote all credential values"],"tags":["xray","go","json","socks","config"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}