cloudflare/cloudflared · warning

failed to parse ICMPv6

Error message

failed to parse ICMPv6

What it means

The IPv6 branch of Decoder.Decode parses the ICMPv6 header+payload with icmp.ParseMessage using the ICMPv6 protocol number. Failure means the bytes following the IPv6 header are not a valid ICMPv6 message; the error is wrapped and Decode fails for this packet.

Source

Thrown at packet/decoder.go:171

			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
		}
	}
	layers := make([]string, len(decoded))
	for i, l := range decoded {
		layers[i] = l.String()
	}
	return nil, fmt.Errorf("Expect to decode IP and ICMP layers, got %s", layers)
}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Inspect the raw IPv6 packet's next-header and payload to confirm it is genuinely ICMPv6.
  2. Drop the malformed packet and continue; the tunnel proxy can operate without decoding every ICMPv6 datagram.
  3. Check for truncation in the path delivering packets to the decoder (MTU/fragmentation issues).
  4. In tests, construct valid ICMPv6 with icmp.ParseMessage-compatible marshaling.

Example fix

// before
if _, err := decoder.Decode(buf); err != nil { return err }
// after
if _, err := decoder.Decode(buf); err != nil {
    log.Debug().Err(err).Msg("skipping invalid icmpv6 packet")
    return nil
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity check before decode: IPv6 (40-byte header) + 8-byte ICMPv6 header
func plausiblyICMPv6(b []byte) bool {
    if len(b) < 48 {
        return false
    }
    return b[6] == 58 // next header == ICMPv6
}

Try / catch

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

Prevention

When it happens

Trigger: Decode is called on a datagram classified as LayerTypeICMPv6 whose Contents/Payload are truncated, corrupted, or not ICMPv6 (wrong protocol payload inside the IPv6 packet).

Common situations: Corrupt datagrams delivered over the QUIC tunnel, misrouted packets where the payload is actually TCP/UDP rather than ICMPv6, or synthetic test data that is malformed.

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/60c8b99dec7898d1. Report an issue: GitHub.