XTLS/Xray-core · error

Failed to build Hysteria config.

Error message

Failed to build Hysteria config.

What it means

Thrown while building the top-level streamSettings when the 'hysteria' transport block is present but HysteriaSettings.Build() fails. This is a wrapper error: the real cause is chained via .Base(err) and comes from the Hysteria transport config builder itself (e.g. invalid bandwidth strings or missing required fields). It aborts config compilation before any network activity starts.

Source

Thrown at infra/conf/transport_internet.go:188

		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
			ProtocolName: "websocket",
			Settings:     serial.ToTypedMessage(ts),
		})
	}
	if c.HTTPUPGRADESettings != nil {
		hs, err := c.HTTPUPGRADESettings.Build()
		if err != nil {
			return nil, errors.New("Failed to build HTTPUpgrade config.").Base(err)
		}
		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 {

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Read the chained cause after 'Failed to build Hysteria config.': the Base(err) text names the exact invalid field; fix that field.
  2. Compare your hysteria transportSettings keys against the HysteriaSettings struct in infra/conf (field names and units).
  3. Regenerate/validate the config with `xray run -test -c config.json` (or equivalent) before deploying.

Example fix

// before
"transportSettings": { "brutalUp": "100mbps" } // malformed/unsupported value
// after
"transportSettings": { "brutalUp": "100 mbps" } // correct syntax per Bandwidth parser
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate the hysteria block shape before Build()
func hysteriaSettingsLookSane(h map[string]any) bool {
    if h == nil { return true } // absent is fine
    for _, k := range []string{"brutalUp", "brutalDown"} {
        if v, ok := h[k]; ok && v == nil { return false }
    }
    return true
}

Type guard

func isHysteriaBlockPresent(s map[string]any) bool {
    ts, ok := s["transportSettings"].(map[string]any)
    if !ok { return false }
    _, present := ts["hysteria"]
    return present
}

Try / catch

cfg, err := jsonToStreamSettings(raw)
if err != nil {
    if strings.Contains(err.Error(), "Failed to build Hysteria config.") {
    // unwrap errors.Unwrap(err) to reach the field-level cause and report it
    }
    return fmt.Errorf("config build failed: %w", err)
}

Prevention

When it happens

Trigger: A JSON config with "streamSettings": {"transport": "hysteria", "transportSettings": {...}} (parsed into HysteriaSettings) whose inner Build() returns an error, e.g. a malformed BrutalUp/BrutalDown bandwidth value or another invalid sub-field.

Common situations: Copying a Hysteria block from a different fork/version whose schema differs; typoing a bandwidth string ("100mbps" vs "100 mbps"); enabling hysteria transport without required parameters.

Related errors


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