{"record":{"id":"4df4aacc6bc75fcb","repo":"XTLS/Xray-core","slug":"brutaldown-must-be-at-least-65536-bytes-per-second","errorCode":null,"errorMessage":"BrutalDown must be at least 65536 bytes per second","messagePattern":"BrutalDown must be at least 65536 bytes per second","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_internet.go","lineNumber":242,"sourceCode":"\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn nil, errors.New(\"unknown bbr profile\")\n\t\t\t}\n\n\t\t\tup, err := c.FinalMask.QuicParams.BrutalUp.Bps()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdown, err := c.FinalMask.QuicParams.BrutalDown.Bps()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tif up > 0 && up < 65536 {\n\t\t\t\treturn nil, errors.New(\"BrutalUp must be at least 65536 bytes per second\")\n\t\t\t}\n\t\t\tif down > 0 && down < 65536 {\n\t\t\t\treturn nil, errors.New(\"BrutalDown must be at least 65536 bytes per second\")\n\t\t\t}\n\n\t\t\tc.FinalMask.QuicParams.Congestion = strings.ToLower(c.FinalMask.QuicParams.Congestion)\n\t\t\tswitch c.FinalMask.QuicParams.Congestion {\n\t\t\tcase \"\", \"brutal\", \"reno\", \"bbr\":\n\t\t\tcase \"force-brutal\":\n\t\t\t\tif up == 0 {\n\t\t\t\t\treturn nil, errors.New(\"force-brutal requires up\")\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn nil, errors.New(\"unknown congestion control: \", c.FinalMask.QuicParams.Congestion, \", valid values: reno, bbr, brutal, force-brutal\")\n\t\t\t}\n\n\t\t\tif (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) {\n\t\t\t\treturn nil, errors.New(\"Interval must be at least 5\")\n\t\t\t}\n\n\t\t\tif c.FinalMask.QuicParams.InitStreamReceiveWindow > 0 && c.FinalMask.QuicParams.InitStreamReceiveWindow < 16384 {","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_internet.go#L224-L260","documentation":"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.","triggerScenarios":"\"quicParams\": { \"brutalDown\": \"64 kbps\" } (64000 bits/s = 8000 B/s < 65536 B/s).","commonSituations":"Bits/bytes confusion; copying a down rate below 512 kBps; keeping a placeholder small value during testing.","solutions":["Set brutalDown to at least 65536 bytes/second, e.g. \"1 MBps\".","Or omit brutalDown if downstream rate should not be pinned.","Remember the threshold is in bytes per second (65536 B/s = 524288 bps)."],"exampleFix":"// before\n\"quicParams\": { \"brutalDown\": \"64 kbps\" }\n// after\n\"quicParams\": { \"brutalDown\": \"1 MBps\" }","handlingStrategy":"validation","validationCode":"func brutalDownOK(raw any) bool {\n    s, _ := raw.(string)\n    if s == \"\" { return true }\n    bps, err := parseBandwidthToBytesPerSec(s)\n    return err == nil && (bps == 0 || bps >= 65536)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use byte-based units ('512 kBps' minimum) for both brutal directions.","Validate both directions together in one check before deploy.","Do not reuse bitrate numbers from link specs without converting bits to bytes."],"tags":["go","xray","config","quic","brutal","bandwidth","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}