ginuerzh/gost · error

write: data maximum exceeded

Error message

write: data maximum exceeded

What it means

relayConn.Write buffers data to be relayed and prefixes it with a 2-byte length, so payloads are limited to 0xFFFF (65535) bytes. A Write with a larger buffer cannot be framed and is rejected before any bytes are queued.

Source

Thrown at relay.go:325

	dlen := int(binary.BigEndian.Uint16(bb[:]))
	if len(b) >= dlen {
		return io.ReadFull(c.Conn, b[:dlen])
	}
	buf := make([]byte, dlen)
	_, err = io.ReadFull(c.Conn, buf)
	n = copy(b, buf)
	return
}

func (c *relayConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
	n, err = c.Read(b)
	addr = c.Conn.RemoteAddr()
	return
}

func (c *relayConn) Write(b []byte) (n int, err error) {
	if len(b) > 0xFFFF {
		err = errors.New("write: data maximum exceeded")
		return
	}
	n = len(b) // force byte length consistent
	if c.wbuf.Len() > 0 {
		if c.udp {
			var bb [2]byte
			binary.BigEndian.PutUint16(bb[:2], uint16(len(b)))
			c.wbuf.Write(bb[:])
			c.headerSent = true
		}
		c.wbuf.Write(b) // append the data to the cached header
		// _, err = c.Conn.Write(c.wbuf.Bytes())
		// c.wbuf.Reset()
		_, err = c.wbuf.WriteTo(c.Conn)
		return
	}

	if !c.udp {

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Write in chunks of at most 0xFFFF bytes
  2. Reduce the read/copy buffer size to <= 64KB
  3. If you own the relay protocol, ensure both ends agree on the framing limit

Example fix

// before
buf := make([]byte, 128*1024)
n, _ := src.Read(buf)
relay.Write(buf[:n]) // fails when n > 65535
// after
const maxChunk = 0xFFFF
for len(data) > 0 {
    c := data
    if len(c) > maxChunk { c = c[:maxChunk] }
    if _, err := relay.Write(c); err != nil { return err }
    data = data[len(c):]
}
Defensive patterns

Strategy: validation

Validate before calling

if len(b) > 0xFFFF {
    return errors.New("payload exceeds relay frame limit (65535)")
}

Try / catch

if _, err := relay.Write(chunk); err != nil {
    return fmt.Errorf("relay write failed: %w", err)
}

Prevention

When it happens

Trigger: Calling Write (directly or via io.Copy / WriteTo) with a slice longer than 65535 bytes on a relayConn.

Common situations: Large reads from a source conn (io.Copy with a >64KB buffer) piped into the relay connection without chunking.

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/480afa2dc2d79900. Report an issue: GitHub.