{"record":{"id":"d76a3b9b82f8ee92","repo":"XTLS/Xray-core","slug":"failed-to-build-sockopt","errorCode":null,"errorMessage":"Failed to build sockopt.","messagePattern":"Failed to build sockopt\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_internet.go","lineNumber":198,"sourceCode":"\t\tconfig.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{\n\t\t\tProtocolName: \"httpupgrade\",\n\t\t\tSettings:     serial.ToTypedMessage(hs),\n\t\t})\n\t}\n\tif c.HysteriaSettings != nil {\n\t\ths, err := c.HysteriaSettings.Build()\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"Failed to build Hysteria config.\").Base(err)\n\t\t}\n\t\tconfig.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{\n\t\t\tProtocolName: \"hysteria\",\n\t\t\tSettings:     serial.ToTypedMessage(hs),\n\t\t})\n\t}\n\tif c.SocketSettings != nil {\n\t\tss, err := c.SocketSettings.Build()\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"Failed to build sockopt.\").Base(err)\n\t\t}\n\t\tconfig.SocketSettings = ss\n\t}\n\n\tif c.FinalMask != nil {\n\t\tfor _, mask := range c.FinalMask.Tcp {\n\t\t\tu, err := mask.Build(true)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.New(\"failed to build mask with type \", mask.Type).Base(err)\n\t\t\t}\n\t\t\tconfig.Tcpmasks = append(config.Tcpmasks, serial.ToTypedMessage(u))\n\t\t}\n\t\tfor _, mask := range c.FinalMask.Udp {\n\t\t\tu, err := mask.Build(false)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.New(\"failed to build mask with type \", mask.Type).Base(err)\n\t\t\t}\n\t\t\tconfig.Udpmasks = append(config.Udpmasks, serial.ToTypedMessage(u))","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_internet.go#L180-L216","documentation":"Thrown when streamSettings.sockopt is set but SocketSettings.Build() fails. It is a wrapper: the underlying error (chained with .Base(err)) typically comes from invalid socket options such as a bad mark, dangling dialer/redirect strategy, or an unusable bind address. The outer message only tells you the failure is in the sockopt block.","triggerScenarios":"Config contains \"sockopt\": { ... } with invalid contents, e.g. tcpKeepAliveInterval out of range, a bad domainStrategy value, or a dialerProxy tag that fails to resolve during sockopt building.","commonSituations":"Hand-editing sockopt copied from another machine (e.g. tcpFastOpen / mark values not supported on the platform); typos in enum-like strings such as domainStrategy; using an old sockopt schema with a newer binary.","solutions":["Inspect the full error chain; the Base(err) message identifies the exact sockopt field that failed.","Check every field under sockopt against SocketConfig in infra/conf (valid ranges and enum values).","Temporarily remove the sockopt block to confirm the rest of the config builds, then re-add fields one by one."],"exampleFix":"// before\n\"sockopt\": { \"domainStrategy\": \"UseIPv4Only\", \"tcpKeepAliveInterval\": -1 }\n// after\n\"sockopt\": { \"domainStrategy\": \"UseIPv4Only\", \"tcpKeepAliveInterval\": 100 }","handlingStrategy":"try-catch","validationCode":"// sanity-check sockopt numbers before handing config to xray\nfunc sockoptLooksValid(so map[string]any) bool {\n    if v, ok := so[\"tcpKeepAliveInterval\"].(float64); ok && v < 0 { return false }\n    if v, ok := so[\"tcpKeepAliveIdle\"].(float64); ok && v < 0 { return false }\n    return true\n}","typeGuard":"func hasSockopt(s map[string]any) bool {\n    ss, ok := s[\"streamSettings\"].(map[string]any)\n    if !ok { return false }\n    _, present := ss[\"sockopt\"]\n    return present\n}","tryCatchPattern":"if err := buildConfig(doc); err != nil {\n    if strings.Contains(err.Error(), \"Failed to build sockopt.\") {\n        // surface the Base(err) cause to the user with the offending sockopt field\n    }\n    return err\n}","preventionTips":["Validate sockopt values against the current SocketConfig struct after every xray upgrade.","Avoid platform-specific sockopt values (mark, interface) on machines that lack them.","Use a config linter/schema validator in the deployment pipeline."],"tags":["go","xray","config","sockopt","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}