AdguardTeam/AdGuardHome · error

decoding u%d: %w

Error message

decoding u%d: %w

What it means

Returned by parseDHCPOptionUint when a DHCP option typed u8 or u16 fails strconv.ParseUint with the given bit size. The message embeds the bit size ('decoding u8:' / 'decoding u16:'). Values must be base-10 integers within 0–255 (u8) or 0–65535 (u16).

Source

Thrown at internal/dhcpd/options_unix.go:96

// 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
}

// parseDHCPOptionUint parses a DHCP option as an unsigned integer.  bitSize is
// expected to be 8 or 16.
func parseDHCPOptionUint(s string, bitSize int) (val dhcpv4.OptionValue, err error) {
	var v uint64
	v, err = strconv.ParseUint(s, 10, bitSize)
	if err != nil {
		return nil, fmt.Errorf("decoding u%d: %w", bitSize, err)
	}

	switch bitSize {
	case 8:
		return dhcpv4.OptionGeneric{Data: []byte{uint8(v)}}, nil
	case 16:
		return dhcpv4.Uint16(v), nil
	default:
		return nil, fmt.Errorf("unsupported size of integer %d", bitSize)
	}
}

// parseDHCPOptionBool parses a DHCP option as a boolean value.  See
// [strconv.ParseBool] for available values.
func parseDHCPOptionBool(s string) (val dhcpv4.OptionValue, err error) {
	var v bool
	v, err = strconv.ParseBool(s)
	if err != nil {

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Clamp to range: 0–255 for u8, 0–65535 for u16, decimal only
  2. Strip units and whitespace from the value
  3. Double-check the vendor's option table for whether the value is decimal or hex and convert to decimal

Example fix

// before
{"code":21,"type":"u8","value":"300"}
// -> decoding u8: strconv.ParseUint: parsing "300": value out of range

// after
{"code":21,"type":"u8","value":"255"}
Defensive patterns

Strategy: validation

Validate before calling

func uintOK(s string, bits int) bool {
	v, err := strconv.ParseUint(strings.TrimSpace(s), 10, bits)
	return err == nil && (bits == 8 && v <= 255 || bits == 16 && v <= 65535)
}

Try / catch

if _, err := strconv.ParseUint(s, 10, bitSize); err != nil {
    if ne, ok := err.(*strconv.NumError); ok && ne.Err == strconv.ErrRange {
        // value exceeds 255/65535: clamp or reject
    }
}

Prevention

When it happens

Trigger: Setting a u8 option to 256+, a negative number, a hex value like 0x2A, or a non-numeric string; a u16 option above 65535; empty string.

Common situations: Copy-pasting MTU or TTL values with units ('1500 bytes'); vendor tables listing option values in hex; off-by-one assumptions about inclusive bounds.

Related errors


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