cloudflare/cloudflared · warning

failed to parse ICMPv4 message

Error message

failed to parse ICMPv4 message

What it means

Decoder.Decode reconstructs ICMPv4 packets: after parsing the IPv4 header, it feeds the concatenated ICMP header+payload bytes to golang.org/x/net/icmp's ParseMessage. If those bytes are not a valid ICMPv4 message, the parse error is wrapped with this message and Decode returns nil error result.

Source

Thrown at packet/decoder.go:158

}

func (pd *ICMPDecoder) Decode(packet RawPacket) (*ICMP, error) {
	// Should decode to IP and optionally ICMP layer
	decoded, err := pd.decodeByVersion(packet.Data)
	if err != nil {
		return nil, err
	}

	for _, layerType := range decoded {
		switch layerType {
		case layers.LayerTypeICMPv4:
			ipv4, err := newIPv4(pd.ipv4)
			if err != nil {
				return nil, err
			}
			msg, err := icmp.ParseMessage(int(layers.IPProtocolICMPv4), append(pd.icmpv4.Contents, pd.icmpv4.Payload...))
			if err != nil {
				return nil, errors.Wrap(err, "failed to parse ICMPv4 message")
			}
			return &ICMP{
				IP:      ipv4,
				Message: msg,
			}, nil
		case layers.LayerTypeICMPv6:
			ipv6, err := newIPv6(pd.ipv6)
			if err != nil {
				return nil, err
			}
			msg, err := icmp.ParseMessage(int(layers.IPProtocolICMPv6), append(pd.icmpv6.Contents, pd.icmpv6.Payload...))
			if err != nil {
				return nil, errors.Wrap(err, "failed to parse ICMPv6")
			}
			return &ICMP{
				IP:      ipv6,
				Message: msg,
			}, nil

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Log the raw packet bytes to confirm the ICMPv4 header (type/code/checksum) is complete and well-formed.
  2. Verify the sender/edge is forwarding full ICMP datagrams without truncation.
  3. Handle the decode error gracefully (drop the packet) — for a tunnel proxy this usually indicates a corrupt datagram, not a local bug.
  4. If reproducing in tests, build messages with icmp.Message.Marshal instead of hand-crafted bytes.

Example fix

// before
c, err := decoder.Decode(rawPacket)
if err != nil { return err }
// after
c, err := decoder.Decode(rawPacket)
if err != nil {
    log.Debug().Err(err).Msg("dropping malformed icmp packet")
    return nil // skip malformed packet
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity check before decode: at least an IPv4 header + 8-byte ICMP header
func plausiblyICMPv4(b []byte) bool {
    if len(b) < 28 {
        return false
    }
    return b[9] == 1 // protocol == ICMP
}

Try / catch

decoded, err := decoder.Decode(raw)
if err != nil {
    log.Debug().Err(err).Msg("dropping undecodable packet")
    return nil
}

Prevention

When it happens

Trigger: Calling packet.Decoder.Decode (via handlePacket/handleFullPacket on QUIC/UDP datagrams) with a packet whose ICMPv4 contents/payload are truncated or malformed, so icmp.ParseMessage fails.

Common situations: Corrupted or truncated datagrams from the edge, packets reassembled incorrectly, or tests feeding synthetic bytes that do not form valid ICMPv4 (see TestDecodeBadPackets).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/f9ce4db493057463. Report an issue: GitHub.