{"record":{"id":"666d946cce8e6b70","repo":"XTLS/Xray-core","slug":"brutal","errorCode":null,"errorMessage":"brutal","messagePattern":"brutal","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"transport/internet/splithttp/dialer.go","lineNumber":271,"sourceCode":"\t\t\t\t\t\treturn nil, errors.New(\"mask err\").Base(err)\n\t\t\t\t\t}\n\t\t\t\t\tpktConn = newConn\n\t\t\t\t}\n\n\t\t\t\tconn, err := quic.DialEarly(ctx, pktConn, udpAddr, tlsCfg, cfg)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tcontext.AfterFunc(conn.Context(), func() { pktConn.Close() })\n\n\t\t\t\tswitch quicParams.Congestion {\n\t\t\t\tcase \"reno\":\n\t\t\t\tcase \"\", \"bbr\":\n\t\t\t\t\tcongestion.UseBBR(conn, bbr.Profile(quicParams.BbrProfile))\n\t\t\t\tcase \"force-brutal\":\n\t\t\t\t\tcongestion.UseBrutal(conn, quicParams.BrutalUp)\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(quicParams.Congestion)\n\t\t\t\t}\n\n\t\t\t\treturn conn, nil\n\t\t\t},\n\t\t}\n\t} else if httpVersion == \"2\" {\n\t\tif keepAlivePeriod == 0 {\n\t\t\tkeepAlivePeriod = net.ChromeH2KeepAlivePeriod\n\t\t}\n\t\tif keepAlivePeriod < 0 {\n\t\t\tkeepAlivePeriod = 0\n\t\t}\n\t\ttransport = &http2.Transport{\n\t\t\tDialTLSContext: func(ctxInner context.Context, network string, addr string, cfg *gotls.Config) (net.Conn, error) {\n\t\t\t\treturn dialContext(ctxInner)\n\t\t\t},\n\t\t\tIdleConnTimeout: net.ConnIdleTimeout,\n\t\t\tReadIdleTimeout: keepAlivePeriod,","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/splithttp/dialer.go#L253-L289","documentation":"The splithttp dialer panicked with the raw congestion-controller name as the panic value while setting up a QUIC (HTTP/3) connection. The switch only accepts \"reno\", \"\"/\"bbr\", and \"force-brutal\"; any other string in the transport config's congestion field hits default: panic(quicParams.Congestion). The panic message 'brutal' appears when the configured value is literally the string 'brutal' — a near-miss of the accepted 'force-brutal'.","triggerScenarios":"Configuring splithttp QUIC congestion to any value outside {\"reno\", \"\", \"bbr\", \"force-brutal\"} — most commonly typing \"brutal\" instead of \"force-brutal\", or \"cubic\"/\"newreno\" from other tools' vocabularies. Panics at dial time, so the outbound connection crashes the process or goroutine depending on recover() coverage.","commonSituations":"Copy-pasting configs from other proxies whose brutal mode is spelled 'brutal'; upgrading configs written for a build that accepted more names; typo in JSON/YAML config.","solutions":["Change the congestion setting to an accepted value: \"force-brutal\" (with brutalUp bandwidth set), \"bbr\" or \"\" (default), or \"reno\".","If you wanted the brutal (TCP-like fixed-rate) controller, use exactly \"force-brutal\" and configure its BrutalUp mbps value.","Validate config at load time instead of panicking at dial time (see validationCode)."],"exampleFix":"// before (config.json)\n\"congestion\": \"brutal\"\n// after\n\"congestion\": \"force-brutal\"","handlingStrategy":"validation","validationCode":"validCongestion := map[string]bool{\"\": true, \"reno\": true, \"bbr\": true, \"force-brutal\": true}\nif !validCongestion[quicParams.Congestion] {\n    return fmt.Errorf(\"invalid congestion %q: use \\\"reno\\\", \\\"bbr\\\" or \\\"force-brutal\\\"\", quicParams.Congestion)\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        return nil, fmt.Errorf(\"splithttp dial failed (congestion=%q): %v\", quicParams.Congestion, r)\n    }\n}()","preventionTips":["Validate congestion strings at config load, not at dial time.","Remember the brutal spelling is \"force-brutal\", never \"brutal\".","Lint shared config snippets for accepted enum values before deploying."],"tags":["quic","congestion-control","panic","config","splithttp"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}