XTLS/Xray-core · error
Failed to build "downloadSettings".
Error message
Failed to build "downloadSettings".
What it means
When "downloadSettings" is present and mode is not stream-one, SplitHTTPConfig.Build() calls DownloadSettings.Build() (a full StreamConfig build) and wraps any failure at transport_method.go:503-506. The base error identifies the nested failure: bad transport name, invalid transportSettings for the chosen download transport (tcp/kcp/ws/http/grpc etc.), invalid security settings, or invalid proxySettings.
Source
Thrown at infra/conf/transport_method.go:505
SessionIDTable: c.SessionIDTable,
SessionIDLength: newRangeConfig(c.SessionIDLength),
Xmux: &splithttp.XmuxConfig{
MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency),
MaxConnections: newRangeConfig(c.Xmux.MaxConnections),
CMaxReuseTimes: newRangeConfig(c.Xmux.CMaxReuseTimes),
HMaxRequestTimes: newRangeConfig(c.Xmux.HMaxRequestTimes),
HMaxReusableSecs: newRangeConfig(c.Xmux.HMaxReusableSecs),
HKeepAlivePeriod: c.Xmux.HKeepAlivePeriod,
},
}
if c.DownloadSettings != nil {
if c.Mode == "stream-one" {
return nil, errors.New(`Can not use "downloadSettings" in "stream-one" mode.`)
}
var err error
if config.DownloadSettings, err = c.DownloadSettings.Build(); err != nil {
return nil, errors.New(`Failed to build "downloadSettings".`).Base(err)
}
}
return config, nil
}
func roomSize(tableSize int, min, max int32) *big.Int {
base := big.NewInt(int64(tableSize))
sum := new(big.Int)
term := new(big.Int)
for k := min; k <= max; k++ {
term.Exp(base, big.NewInt(int64(k)), nil)
sum.Add(sum, term)
}
return sum
}
type KCPConfig struct {View on GitHub (pinned to 7d214f8b09)
Solutions
- Read the base (chained) error — it is the inner StreamConfig build failure and names the real problem
- Fix the nested transportSettings/tlsSettings per that inner error's documentation
- Ensure "transport" inside downloadSettings.transportSettings is a registered stream transport (tcp, rawtcp, ws, http, h2, grpc, gun, splithttp, kcp...)
- Simplify: omit downloadSettings to use the same transport for both directions while testing
Example fix
// before
"downloadSettings": { "transportSettings": { "transport": "h3" } }
// after
"downloadSettings": { "transportSettings": { "transport": "http", "transportSettings": { "host": "dl.example.com", "path": /dl" } } } Defensive patterns
Strategy: try-catch
Try / catch
// Go: wrap and unwrap the chained base error to reach the inner StreamConfig failure
if _, err := cfg.Build(); err != nil {
if strings.Contains(err.Error(), `Failed to build "downloadSettings"`) {
// err chain's Base holds the nested cause; log the full chain
log.Printf("nested download transport invalid: %v", err)
}
return err
} Prevention
- Treat downloadSettings as a full StreamConfig: validate its transport name and settings the same way as a top-level stream
- Read the base error — it names the inner field that failed
- Test with downloadSettings omitted first, then add it back
When it happens
Trigger: "downloadSettings": {"transportSettings": {"transport": "h2"}} where h2 is not a registered transport; or a tcp downloadSettings with an invalid header block (reuses error 400/401 logic); or "security": "tls" with a malformed tlsSettings object.
Common situations: Splitting up/down transports across CDNs and typo-ing the download transport type; downloadSettings copied from an outbound streamSettings retaining fields invalid in this position; version drift where a transport was renamed.
Related errors
- Can not use "downloadSettings" in "stream-one" mode.
- Failed to unmarshal "extra".
- unsupported mode:
- "headers" can't contain "host"
- xPaddingBytes cannot be disabled
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/113002915d7ad9be.
Report an issue: GitHub.