{"record":{"id":"5b4881756a35baea","repo":"fatedier/frp","slug":"truncated-zone","errorCode":null,"errorMessage":"truncated zone","messagePattern":"truncated zone","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/msg/udp_binary.go","lineNumber":208,"sourceCode":"\tswitch family {\n\tcase 4:\n\t\tipLen = net.IPv4len\n\tcase 6:\n\t\tipLen = net.IPv6len\n\tdefault:\n\t\treturn nil, offset, fmt.Errorf(\"unknown address family %d\", family)\n\t}\n\tif len(body)-offset < ipLen+3 {\n\t\treturn nil, offset, fmt.Errorf(\"truncated address\")\n\t}\n\tip := append(net.IP(nil), body[offset:offset+ipLen]...)\n\toffset += ipLen\n\tport := binary.BigEndian.Uint16(body[offset : offset+2])\n\toffset += 2\n\tzoneLen := int(body[offset])\n\toffset++\n\tif len(body)-offset < zoneLen {\n\t\treturn nil, offset, fmt.Errorf(\"truncated zone\")\n\t}\n\tzoneBytes := body[offset : offset+zoneLen]\n\tif family == 4 && zoneLen != 0 {\n\t\treturn nil, offset, fmt.Errorf(\"IPv4 zone is forbidden\")\n\t}\n\tif !utf8.Valid(zoneBytes) {\n\t\treturn nil, offset, fmt.Errorf(\"zone is not valid UTF-8\")\n\t}\n\toffset += zoneLen\n\treturn &net.UDPAddr{IP: ip, Port: int(port), Zone: string(zoneBytes)}, offset, nil\n}\n\ntype V2BinaryUDPPacketReadWriter struct {\n\tconn *wire.Conn\n}\n\nfunc NewV2BinaryUDPPacketReadWriter(rw io.ReadWriter) *V2BinaryUDPPacketReadWriter {\n\treturn &V2BinaryUDPPacketReadWriter{conn: wire.NewConn(rw)}","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/msg/udp_binary.go#L190-L226","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Treat this as fatal for the connection: close and re-establish the work connection — the stream is desynchronized, so subsequent frames cannot be trusted.","Confirm frpc and frps run the same frp version so the binary codec layout matches.","Remove any intermediary that mangles the TCP stream (some LBs with frame inspection).","If writing a custom encoder, ensure the zone length byte is always written (0 for IPv4)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := rw.ReadMsg(); err != nil {\n\tif strings.Contains(err.Error(), \"truncated\") {\n\t\t// stream is desynchronized or corrupted: close the work connection and let frp re-establish it\n\t\tconn.Close()\n\t\treturn err\n\t}\n}","preventionTips":["Never continue reading a connection after a truncation error — framing is unrecoverable.","Keep frpc and frps on the same release so binary layouts match.","Avoid intermediaries that modify the TCP stream between peers."],"tags":["protocol","binary","udp","frp","corruption"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}