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
- Clamp to range: 0–255 for u8, 0–65535 for u16, decimal only
- Strip units and whitespace from the value
- 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
- Decimal-only values in 0–255 (u8) / 0–65535 (u16)
- Strip units like 'bytes' from vendor tables
- Convert hex codes to decimal before entering
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.