cloudflare/cloudflared · error

expect IPv4, but %s is IPv6

Error message

expect IPv4, but %s is IPv6

What it means

determineICMPv4Src resolves the local IPv4 source address used for ICMPv4 echo (ping) traffic. If the user supplied an explicit source address via configuration and that address parses as IPv6 rather than IPv4, the function returns this error. Cloudflared requires an IPv4 address to send and listen for ICMPv4 packets.

Source

Thrown at cmd/cloudflared/tunnel/configuration.go:400

	if zone != "" {
		logger.Info().Msgf("ICMP proxy will use %s in zone %s as source for IPv6", ipv6Src, zone)
	} else {
		logger.Info().Msgf("ICMP proxy will use %s as source for IPv6", ipv6Src)
	}

	return ipv4Src, ipv6Src, nil
}

func determineICMPv4Src(userDefinedSrc string, logger *zerolog.Logger) (netip.Addr, error) {
	if userDefinedSrc != "" {
		addr, err := netip.ParseAddr(userDefinedSrc)
		if err != nil {
			return netip.Addr{}, err
		}
		if addr.Is4() {
			return addr, nil
		}
		return netip.Addr{}, fmt.Errorf("expect IPv4, but %s is IPv6", userDefinedSrc)
	}

	addr, err := findLocalAddr(net.ParseIP("192.168.0.1"), 53)
	if err != nil {
		addr = netip.IPv4Unspecified()
		logger.Debug().Err(err).Msgf("Failed to determine the IPv4 for this machine. It will use %s to send/listen for ICMPv4 echo", addr)
	}
	return addr, nil
}

type interfaceIP struct {
	name string
	ip   net.IP
}

func determineICMPv6Src(userDefinedSrc string, logger *zerolog.Logger, ipv4Src netip.Addr) (addr netip.Addr, zone string, err error) {
	if userDefinedSrc != "" {
		addr, err := netip.ParseAddr(userDefinedSrc)

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Set the ICMPv4 source to a valid IPv4 address (e.g. 192.168.1.10)
  2. Remove the explicit source so cloudflared discovers one via findLocalAddr (falls back to IPv4 unspecified)
  3. If you intended IPv6, set the ICMPv6 source field instead

Example fix

// before
$ cloudflared tunnel run --icmpv4-src ::1

// after
$ cloudflared tunnel run --icmpv4-src 192.168.1.10
Defensive patterns

Strategy: validation

Validate before calling

addr, err := netip.ParseAddr(src)
if err != nil || !addr.Is4() {
    return fmt.Errorf("--icmpv4-src must be an IPv4 address, got %q", src)
}

Type guard

func isIPv4Literal(s string) bool { a, err := netip.ParseAddr(s); return err == nil && a.Is4() }

Try / catch

if _, err := determineICMPv4Src(c); err != nil {
    logger.Error().Err(err).Msg("invalid ICMPv4 source")
    os.Exit(1)
}

Prevention

When it happens

Trigger: Setting the ICMPv4 source (e.g. `--icmpv4-src` or config equivalent) to an IPv6 literal like `::1` or `2001:db8::1`, causing `addr.Is4()` to fail after parsing the user-defined address.

Common situations: Admins swap the v4 and v6 source flags by mistake; documentation examples use one field but the operator fills the other; a hostname resolves to an AAAA record where an A address was expected.

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