txthinking/brook · error
cannot create exchanger from
Error message
cannot create exchanger from
What it means
CreateExchanger dispatches on the brook link's Kind to build a client/server exchanger pair. If the kind does not match any supported scheme (ws, wss, quic, etc.), it returns this error with the unrecognized kind appended. It means the link string's scheme prefix is not a protocol this build supports.
Source
Thrown at brooklink.go:276
}
rc, err := QUICDialUDP(src, socks5.ToAddress(dstb[0], dstb[1:len(dstb)-2], dstb[len(dstb)-2:]), blk.Address, blk.Tc, udptimeout)
if err != nil {
return nil, nil, err
}
var sc Exchanger
if blk.V.Get("withoutBrookProtocol") != "true" {
sc, err = NewPacketClient(blk.Password, src, rc, udptimeout, dstb)
}
if blk.V.Get("withoutBrookProtocol") == "true" {
sc, err = NewSimplePacketClient(blk.Password, src, rc, udptimeout, dstb)
}
if err != nil {
rc.Close()
return nil, nil, err
}
return sc, rc, nil
}
return nil, nil, errors.New("cannot create exchanger from " + blk.Kind)
}
func (x *BrookLink) PrepareSocks5Server(addr, ip string, tcptimeout, udptimeout int) error {
if err := limits.Raise(); err != nil {
Log(Error{"when": "try to raise system limits", "warning": err.Error()})
}
if x.Kind == "quicserver" {
if runtime.GOOS == "linux" {
c := exec.Command("sysctl", "-w", "net.core.rmem_max=2500000")
b, err := c.CombinedOutput()
if err != nil {
Log(Error{"when": "try to raise UDP Receive Buffer Size", "warning": string(b)})
}
}
if runtime.GOOS == "darwin" {
c := exec.Command("sysctl", "-w", "kern.ipc.maxsockbuf=3014656")
b, err := c.CombinedOutput()
if err != nil {View on GitHub (pinned to 5cd13ef3b1)
Solutions
- Print/inspect blk.Kind and correct the scheme in the link string to a supported one (ws, wss, quic, etc.)
- Regenerate the link with a matching brook version so the scheme is recognized
- Upgrade the library if the link uses a newer protocol kind your build doesn't support
- If Kind is empty, check that the link URL was parsed correctly and has a scheme prefix
Example fix
// before
blk, _ := NewBrookLink("ws4ss://server:443?something")
ex := CreateExchanger(blk)
// after
blk, _ := NewBrookLink("wss://server:443?withoutHeader=true")
ex := CreateExchanger(blk) Defensive patterns
Strategy: validation
Validate before calling
supported := map[string]bool{"ws": true, "wss": true, "quic": true /* per your build */}
if !supported[blk.Kind] {
return fmt.Errorf("unsupported brook kind: %q", blk.Kind)
} Try / catch
sc, rc, err := CreateExchanger(blk)
if err != nil {
if strings.HasPrefix(err.Error(), "cannot create exchanger from") {
log.Printf("unknown brook kind %q — check link scheme", blk.Kind)
}
return err
} Prevention
- Generate links with the same brook version as the consuming library
- Validate scheme prefix before constructing links
- Log blk.Kind on failure to spot typos/empty schemes
When it happens
Trigger: Calling CreateExchanger (directly or via TCPHandle/UDPHandle) with a BrookLink whose Kind string is unknown — e.g. a typo'd or unsupported scheme like 'ws4ss://', an empty scheme, or a scheme added in a newer brook version.
Common situations: Hand-crafted brook:// link strings with wrong scheme; links generated by newer brook clients passed to an older library; empty/malformed link URL where scheme parsing yields "" (note the double space in the message when Kind is empty).
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- socks5 server requires a clear IP for UDP, only port is not
- Looks like you want create socks5 from a socks5, you may wan
- --cert must be with absolute path
- --certkey must be with absolute path
AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06).
Data as JSON: /api/errors/5811f92157e7e1f6.
Report an issue: GitHub.