XTLS/Xray-core · error

Failed to build sockopt.

Error message

Failed to build sockopt.

What it means

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.

Source

Thrown at infra/conf/transport_internet.go:198

		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
			ProtocolName: "httpupgrade",
			Settings:     serial.ToTypedMessage(hs),
		})
	}
	if c.HysteriaSettings != nil {
		hs, err := c.HysteriaSettings.Build()
		if err != nil {
			return nil, errors.New("Failed to build Hysteria config.").Base(err)
		}
		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
			ProtocolName: "hysteria",
			Settings:     serial.ToTypedMessage(hs),
		})
	}
	if c.SocketSettings != nil {
		ss, err := c.SocketSettings.Build()
		if err != nil {
			return nil, errors.New("Failed to build sockopt.").Base(err)
		}
		config.SocketSettings = ss
	}

	if c.FinalMask != nil {
		for _, mask := range c.FinalMask.Tcp {
			u, err := mask.Build(true)
			if err != nil {
				return nil, errors.New("failed to build mask with type ", mask.Type).Base(err)
			}
			config.Tcpmasks = append(config.Tcpmasks, serial.ToTypedMessage(u))
		}
		for _, mask := range c.FinalMask.Udp {
			u, err := mask.Build(false)
			if err != nil {
				return nil, errors.New("failed to build mask with type ", mask.Type).Base(err)
			}
			config.Udpmasks = append(config.Udpmasks, serial.ToTypedMessage(u))

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Inspect the full error chain; the Base(err) message identifies the exact sockopt field that failed.
  2. Check every field under sockopt against SocketConfig in infra/conf (valid ranges and enum values).
  3. Temporarily remove the sockopt block to confirm the rest of the config builds, then re-add fields one by one.

Example fix

// before
"sockopt": { "domainStrategy": "UseIPv4Only", "tcpKeepAliveInterval": -1 }
// after
"sockopt": { "domainStrategy": "UseIPv4Only", "tcpKeepAliveInterval": 100 }
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check sockopt numbers before handing config to xray
func sockoptLooksValid(so map[string]any) bool {
    if v, ok := so["tcpKeepAliveInterval"].(float64); ok && v < 0 { return false }
    if v, ok := so["tcpKeepAliveIdle"].(float64); ok && v < 0 { return false }
    return true
}

Type guard

func hasSockopt(s map[string]any) bool {
    ss, ok := s["streamSettings"].(map[string]any)
    if !ok { return false }
    _, present := ss["sockopt"]
    return present
}

Try / catch

if err := buildConfig(doc); err != nil {
    if strings.Contains(err.Error(), "Failed to build sockopt.") {
        // surface the Base(err) cause to the user with the offending sockopt field
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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