fatedier/frp · error

truncated zone

Error message

truncated zone

What it means

While decoding a v2 binary-encoded UDP address (EncodeUDPPacketBinary format), the zone length byte claims more bytes than remain in the buffer. Every v2 binary UDP address carries a 1-byte zone length even for IPv4; if the packet was truncated mid-address, decoding fails with this error. It signals stream corruption, truncation, or a non-UDP frame being fed to the binary decoder.

Source

Thrown at pkg/msg/udp_binary.go:208

	switch family {
	case 4:
		ipLen = net.IPv4len
	case 6:
		ipLen = net.IPv6len
	default:
		return nil, offset, fmt.Errorf("unknown address family %d", family)
	}
	if len(body)-offset < ipLen+3 {
		return nil, offset, fmt.Errorf("truncated address")
	}
	ip := append(net.IP(nil), body[offset:offset+ipLen]...)
	offset += ipLen
	port := binary.BigEndian.Uint16(body[offset : offset+2])
	offset += 2
	zoneLen := int(body[offset])
	offset++
	if len(body)-offset < zoneLen {
		return nil, offset, fmt.Errorf("truncated zone")
	}
	zoneBytes := body[offset : offset+zoneLen]
	if family == 4 && zoneLen != 0 {
		return nil, offset, fmt.Errorf("IPv4 zone is forbidden")
	}
	if !utf8.Valid(zoneBytes) {
		return nil, offset, fmt.Errorf("zone is not valid UTF-8")
	}
	offset += zoneLen
	return &net.UDPAddr{IP: ip, Port: int(port), Zone: string(zoneBytes)}, offset, nil
}

type V2BinaryUDPPacketReadWriter struct {
	conn *wire.Conn
}

func NewV2BinaryUDPPacketReadWriter(rw io.ReadWriter) *V2BinaryUDPPacketReadWriter {
	return &V2BinaryUDPPacketReadWriter{conn: wire.NewConn(rw)}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Treat this as fatal for the connection: close and re-establish the work connection — the stream is desynchronized, so subsequent frames cannot be trusted.
  2. Confirm frpc and frps run the same frp version so the binary codec layout matches.
  3. Remove any intermediary that mangles the TCP stream (some LBs with frame inspection).
  4. If writing a custom encoder, ensure the zone length byte is always written (0 for IPv4).
Defensive patterns

Strategy: try-catch

Try / catch

if _, err := rw.ReadMsg(); err != nil {
	if strings.Contains(err.Error(), "truncated") {
		// stream is desynchronized or corrupted: close the work connection and let frp re-establish it
		conn.Close()
		return err
	}
}

Prevention

When it happens

Trigger: DecodeUDPPacketBinary (via V2BinaryUDPPacketReadWriter.ReadMsg) receives a payload where the address section ends before family+IP+port+zoneLen fully fit — e.g. a frame cut short by a read timeout, a man-in-the-middle/garbage stream, or a peer using an incompatible binary layout.

Common situations: A TCP connection carrying work-conn UDP traffic is interrupted mid-frame; frpc and frps versions disagree on the binary UDP packet layout; a load balancer or proxy truncates long-lived frames; test harness sends hand-crafted frames with wrong offsets.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/5b4881756a35baea. Report an issue: GitHub.