XTLS/Xray-core · error

BrutalDown must be at least 65536 bytes per second

Error message

BrutalDown must be at least 65536 bytes per second

What it means

Same floor check as BrutalUp but for the downstream bandwidth: if brutalDown is set (> 0) and parses to less than 65536 bytes/second, config building fails. Unset (0) is allowed. The purpose is to prevent Brutal congestion control from being configured with an unusably small down rate.

Source

Thrown at infra/conf/transport_internet.go:242

				}
			default:
				return nil, errors.New("unknown bbr profile")
			}

			up, err := c.FinalMask.QuicParams.BrutalUp.Bps()
			if err != nil {
				return nil, err
			}
			down, err := c.FinalMask.QuicParams.BrutalDown.Bps()
			if err != nil {
				return nil, err
			}

			if up > 0 && up < 65536 {
				return nil, errors.New("BrutalUp must be at least 65536 bytes per second")
			}
			if down > 0 && down < 65536 {
				return nil, errors.New("BrutalDown must be at least 65536 bytes per second")
			}

			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 {

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Set brutalDown to at least 65536 bytes/second, e.g. "1 MBps".
  2. Or omit brutalDown if downstream rate should not be pinned.
  3. Remember the threshold is in bytes per second (65536 B/s = 524288 bps).

Example fix

// before
"quicParams": { "brutalDown": "64 kbps" }
// after
"quicParams": { "brutalDown": "1 MBps" }
Defensive patterns

Strategy: validation

Validate before calling

func brutalDownOK(raw any) bool {
    s, _ := raw.(string)
    if s == "" { return true }
    bps, err := parseBandwidthToBytesPerSec(s)
    return err == nil && (bps == 0 || bps >= 65536)
}

Prevention

When it happens

Trigger: "quicParams": { "brutalDown": "64 kbps" } (64000 bits/s = 8000 B/s < 65536 B/s).

Common situations: Bits/bytes confusion; copying a down rate below 512 kBps; keeping a placeholder small value during testing.

Related errors


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