XTLS/Xray-core · error
InitStreamReceiveWindow must be at least 16384
Error message
InitStreamReceiveWindow must be at least 16384
What it means
QUIC flow-control floor for finalMask.quicParams.initStreamReceiveWindow: any positive value below 16384 bytes is rejected (0 = use default). quic-go requires stream receive windows of at least 16 KiB; smaller windows would break the QUIC transport.
Source
Thrown at infra/conf/transport_internet.go:261
}
c.FinalMask.QuicParams.Congestion = strings.ToLower(c.FinalMask.QuicParams.Congestion)
switch c.FinalMask.QuicParams.Congestion {
case "", "brutal", "reno", "bbr":
case "force-brutal":
if up == 0 {
return nil, errors.New("force-brutal requires up")
}
default:
return nil, errors.New("unknown congestion control: ", c.FinalMask.QuicParams.Congestion, ", valid values: reno, bbr, brutal, force-brutal")
}
if (c.FinalMask.QuicParams.UdpHop.Interval.From != 0 && c.FinalMask.QuicParams.UdpHop.Interval.From < 5) || (c.FinalMask.QuicParams.UdpHop.Interval.To != 0 && c.FinalMask.QuicParams.UdpHop.Interval.To < 5) {
return nil, errors.New("Interval must be at least 5")
}
if c.FinalMask.QuicParams.InitStreamReceiveWindow > 0 && c.FinalMask.QuicParams.InitStreamReceiveWindow < 16384 {
return nil, errors.New("InitStreamReceiveWindow must be at least 16384")
}
if c.FinalMask.QuicParams.MaxStreamReceiveWindow > 0 && c.FinalMask.QuicParams.MaxStreamReceiveWindow < 16384 {
return nil, errors.New("MaxStreamReceiveWindow must be at least 16384")
}
if c.FinalMask.QuicParams.InitConnectionReceiveWindow > 0 && c.FinalMask.QuicParams.InitConnectionReceiveWindow < 16384 {
return nil, errors.New("InitConnectionReceiveWindow must be at least 16384")
}
if c.FinalMask.QuicParams.MaxConnectionReceiveWindow > 0 && c.FinalMask.QuicParams.MaxConnectionReceiveWindow < 16384 {
return nil, errors.New("MaxConnectionReceiveWindow must be at least 16384")
}
if c.FinalMask.QuicParams.MaxIdleTimeout != 0 && (c.FinalMask.QuicParams.MaxIdleTimeout < 4 || c.FinalMask.QuicParams.MaxIdleTimeout > 120) {
return nil, errors.New("MaxIdleTimeout must be between 4 and 120")
}
if c.FinalMask.QuicParams.KeepAlivePeriod != 0 && (c.FinalMask.QuicParams.KeepAlivePeriod < 2 || c.FinalMask.QuicParams.KeepAlivePeriod > 60) {
return nil, errors.New("KeepAlivePeriod must be between 2 and 60")
}
if c.FinalMask.QuicParams.MaxIncomingStreams != 0 && c.FinalMask.QuicParams.MaxIncomingStreams < 8 {
return nil, errors.New("MaxIncomingStreams must be at least 8")View on GitHub (pinned to 7d214f8b09)
Solutions
- Set initStreamReceiveWindow to >= 16384 (bytes), e.g. 8192 KiB style values used in examples (e.g. 8388608).
- Or omit the field to use the library default.
- Prefer tuning maxStreamReceiveWindow rather than shrinking the initial window below the floor.
Example fix
// before
"quicParams": { "initStreamReceiveWindow": 8192 }
// after
"quicParams": { "initStreamReceiveWindow": 8388608 } Defensive patterns
Strategy: validation
Validate before calling
func windowFloorOK(v any, floor int64) bool {
n, ok := v.(float64)
return !ok || n == 0 || int64(n) >= floor
}
// usage: windowFloorOK(qp["initStreamReceiveWindow"], 16384) Prevention
- Use the reference values from example configs (MiB-scale byte counts) for all four windows.
- Enforce a shared 16384-byte floor constant in your config generator.
- Never mix window units (KiB vs bytes) when hand-editing.
When it happens
Trigger: "quicParams": { "initStreamReceiveWindow": 8192 }.
Common situations: Trying to reduce memory by shrinking windows below the protocol minimum; unit confusion (bits vs bytes); carry-over values tuned for TCP buffers.
Related errors
- MaxStreamReceiveWindow must be at least 16384
- InitConnectionReceiveWindow must be at least 16384
- MaxConnectionReceiveWindow must be at least 16384
- unknown bbr profile
- BrutalUp must be at least 65536 bytes per second
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/cd90b7087161d141.
Report an issue: GitHub.