txthinking/brook · error

data too small

Error message

data too small

What it means

SimplePacketServerConnFactory.Handle validates an incoming UDP packet used to establish a packet-based connection. The packet must be at least 32 bytes of password + 4 bytes of big-endian timestamp; if len(b) < 36 the packet is malformed or truncated, and this error is returned before any further processing.

Source

Thrown at simplepacketserverconn.go:42

	"github.com/txthinking/socks5"
)

type SimplePacketServerConnFactory struct {
	Conns map[string]*PacketConn
	Lock  *sync.Mutex
}

func NewSimplePacketServerConnFactory() *SimplePacketServerConnFactory {
	return &SimplePacketServerConnFactory{
		Conns: make(map[string]*PacketConn),
		Lock:  &sync.Mutex{},
	}
}

func (f *SimplePacketServerConnFactory) Handle(addr *net.UDPAddr, b, p []byte, w func([]byte) (int, error), timeout int) (net.Conn, []byte, error) {
	if len(b) < 32+4 {
		return nil, nil, errors.New("data too small")
	}
	if bytes.Compare(p, b[:32]) != 0 {
		return nil, nil, errors.New("Password is wrong")
	}
	i := int64(binary.BigEndian.Uint32(b[32 : 32+4]))
	if time.Now().Unix()-i > 60 {
		return nil, nil, errors.New("Expired request")
	}
	a, h, p, err := socks5.ParseBytesAddress(b[32+4:])
	if err != nil {
		return nil, nil, err
	}
	dst := socks5.ToAddress(a, h, p)
	f.Lock.Lock()
	c, ok := f.Conns[addr.String()+dst]
	f.Lock.Unlock()
	if ok {
		_ = c.In(b[32+4+1+len(h)+2:])

View on GitHub (pinned to 5cd13ef3b1)

Solutions

  1. Update the client to send password (32 bytes) + timestamp (4 bytes) + payload; verify with a length check before sending.
  2. Ensure client and server use the same protocol version and packet framing.
  3. Log the offending source address (addr) to identify scanners or misbehaving clients and drop them silently.
  4. Check network path (MTU, proxies, NAT) for datagram truncation.

Example fix

// before (client)
buf := make([]byte, 32)
copy(buf, password)
conn.Write(buf) // server: "data too small"
// after
buf := make([]byte, 32+4)
copy(buf, password)
binary.BigEndian.PutUint32(buf[32:], uint32(time.Now().Unix()))
buf = append(buf, payload...)
conn.Write(buf)
Defensive patterns

Strategy: validation

Validate before calling

func packetIsValid(b []byte) bool {
    return len(b) >= 32+4
}
// client side, before sending:
// if len(packet) < 36 { return errors.New("packet framing broken") }

Type guard

func isWellFormedPacket(b []byte) bool {
    return len(b) >= 36
}

Try / catch

conn, rest, err := factory.Handle(addr, b, password, w, timeout)
if err != nil {
    if strings.Contains(err.Error(), "data too small") {
        // log addr, drop packet silently; likely scanner/misconfigured client
        return
    }
    return err
}

Prevention

When it happens

Trigger: Calling Handle (directly or via the packet server) with a payload shorter than 36 bytes: an empty datagram, a client sending only the password (32 bytes) without the timestamp/payload, packet truncation, or a client speaking an older/different protocol version.

Common situations: Version mismatch between client and server protocol implementations; port scanners or random UDP traffic hitting the listening socket; MTU/fragmentation dropping the tail of a datagram; misconfigured client omitting the timestamp field.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06). Data as JSON: /api/errors/229c0afc5e028836. Report an issue: GitHub.