XTLS/Xray-core · error

unknown congestion control: + c.FinalMask.QuicParams.Conges

Error message

unknown congestion control:  + c.FinalMask.QuicParams.Congestion + , valid values: reno, bbr, brutal, force-brutal

What it means

Enumerates the allowed congestion control algorithms for finalMask.quicParams: '', 'brutal', 'reno', 'bbr', and 'force-brutal' (the latter additionally requires brutalUp). The value is lowercased first, so case does not matter, but any other string is rejected with the valid values listed in the message.

Source

Thrown at infra/conf/transport_internet.go:253

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

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Set congestion to one of: "reno", "bbr", "brutal", "force-brutal" (case-insensitive).
  2. Remove the field to use the default (empty string is accepted).
  3. If you intended fixed-rate, use "force-brutal" and also set brutalUp >= 65536 B/s.

Example fix

// before
"quicParams": { "congestion": "cubic" }
// after
"quicParams": { "congestion": "bbr" }
Defensive patterns

Strategy: validation

Validate before calling

var validCongestion = map[string]bool{"": true, "brutal": true, "reno": true, "bbr": true, "force-brutal": true}

func congestionOK(qp map[string]any) bool {
    c, _ := qp["congestion"].(string)
    return validCongestion[strings.ToLower(c)]
}

Type guard

type Congestion string

func (c Congestion) Valid() bool {
    switch strings.ToLower(string(c)) {
    case "", "brutal", "reno", "bbr", "force-brutal":
        return true
    }
    return false
}

Prevention

When it happens

Trigger: "quicParams": { "congestion": "cubic" } or any string other than reno/bbr/brutal/force-brutal.

Common situations: Assuming standard QUIC names like 'cubic' or 'newreno' are supported; typos ('bbrr', 'Bruno'); leftover experimental names from older forks.

Related errors


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