XTLS/Xray-core · error

MaxStreamReceiveWindow must be at least 16384

Error message

MaxStreamReceiveWindow must be at least 16384

What it means

Same 16384-byte floor applied to finalMask.quicParams.maxStreamReceiveWindow. A positive value below 16 KiB is invalid because a max stream window smaller than the protocol minimum is contradictory; 0 means unset/default.

Source

Thrown at infra/conf/transport_internet.go:264

			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")
			}

			if c.FinalMask.QuicParams.Debug {

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Set maxStreamReceiveWindow >= 16384 bytes (and >= initStreamReceiveWindow).
  2. Or leave it unset for the default.
  3. Use explicit byte values from the reference configs (e.g. 8388608).

Example fix

// before
"quicParams": { "maxStreamReceiveWindow": 4096 }
// after
"quicParams": { "maxStreamReceiveWindow": 8388608 }
Defensive patterns

Strategy: validation

Validate before calling

func streamWindowsOK(qp map[string]any) bool {
    return windowFloorOK(qp["maxStreamReceiveWindow"], 16384) &&
        windowFloorOK(qp["initStreamReceiveWindow"], 16384)
}

Prevention

When it happens

Trigger: "quicParams": { "maxStreamReceiveWindow": 4096 }.

Common situations: Setting max below init (or below the floor) when trimming buffers; pasting partial numbers; misreading the unit as KiB.

Related errors


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