AdguardTeam/AdGuardHome · error

parsing ip at index %d: %w

Error message

parsing ip at index %d: %w

What it means

Returned by parseDHCPOptionIPs when one element of a comma-separated IP list fails to parse as an IPv4 address. The index (%d) in the message identifies which list position is bad. Used for options taking multiple IPs, like NTP or DNS servers.

Source

Thrown at internal/dhcpd/options_unix.go:69

	// addresses.
	//
	// See https://github.com/AdguardTeam/AdGuardHome/issues/2688.
	if ip, err = netutil.ParseIPv4(s); err != nil {
		return nil, err
	}

	return dhcpv4.IP(ip), nil
}

// parseDHCPOptionIPs parses a DHCP option as a comma-separates list of IP
// addresses.
func parseDHCPOptionIPs(s string) (val dhcpv4.OptionValue, err error) {
	var ips dhcpv4.IPs
	var ip dhcpv4.OptionValue
	for i, ipStr := range strings.Split(s, ",") {
		ip, err = parseDHCPOptionIP(ipStr)
		if err != nil {
			return nil, fmt.Errorf("parsing ip at index %d: %w", i, err)
		}

		ips = append(ips, net.IP(ip.(dhcpv4.IP)))
	}

	return ips, nil
}

// parseDHCPOptionDur parses a DHCP option as a duration in a human-readable
// form.
func parseDHCPOptionDur(s string) (val dhcpv4.OptionValue, err error) {
	var v timeutil.Duration
	err = v.UnmarshalText([]byte(s))
	if err != nil {
		return nil, fmt.Errorf("decoding dur: %w", err)
	}

	return dhcpv4.Duration(v), nil

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Use the reported index to find the exact element: the message says 'parsing ip at index N'
  2. Remove spaces after commas and any trailing comma
  3. Ensure every element is a literal IPv4 dotted-quad (no hostnames, no IPv6)
  4. Validate each element client-side with net.ParseIP/ParseCIDR logic before submitting

Example fix

// before
"value":"192.168.1.1, 192.168.1.2,"  // space + trailing comma
// -> parsing ip at index 1: ...

// after
"value":"192.168.1.1,192.168.1.2"
Defensive patterns

Strategy: validation

Validate before calling

func ipsOK(s string) bool {
	for i, part := range strings.Split(s, ",") {
		if ip := net.ParseIP(strings.TrimSpace(part)); ip == nil || ip.To4() == nil {
			_ = i
			return false
		}
	}
	return true
}

Try / catch

if err := setOption(...); err != nil {
    if m := regexp.MustCompile(`parsing ip at index (\d+)`).FindStringSubmatch(err.Error()); m != nil {
        // fix element at index m[1]
    }
}

Prevention

When it happens

Trigger: Submitting an option of type ip with value "192.168.1.1, 192.168.1.2" where any element is empty, has trailing text, is a hostname instead of an IP, or — notably — contains a space after the comma that fails parsing, or includes an IPv6 literal in an IPv4-only option.

Common situations: Whitespace after commas; accidentally pasting a DNS name; a trailing comma producing an empty last element; mixing IPv6 into an IPv4 list.

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/9f80f776cf881125. Report an issue: GitHub.