AdguardTeam/AdGuardHome · error

decoding dur: %w

Error message

decoding dur: %w

What it means

Returned by parseDHCPOptionDur when a DHCP option typed as duration fails timeutil.Duration.UnmarshalText. Accepts human-readable forms like '1h30m' or Go duration syntax, and rejects plain numbers without units (unless a unit is implied by the specific format) and garbage strings.

Source

Thrown at internal/dhcpd/options_unix.go:84

	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
}

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

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Use Go-style duration strings with explicit units: '3600s', '1h', '1h30m'
  2. Spell units exactly (s, m, h, d where supported) without spaces between number and unit
  3. Test parseability locally: go run - <<<'package main;import("fmt";"time");func main(){_,e:=time.ParseDuration("1h");fmt.Println(e)}'

Example fix

// before
"value":"3600"
// -> decoding dur: time: invalid duration "3600" (missing unit)

// after
"value":"3600s"
Defensive patterns

Strategy: validation

Validate before calling

func durOK(s string) bool {
	_, err := time.ParseDuration(s) // close proxy for timeutil.Duration
	return err == nil
}

Prevention

When it happens

Trigger: Setting an option (e.g. lease time or renew timers) with value '3600' instead of '1h' or '3600s', or with typos like '1hr', '30seconds'.

Common situations: Assuming seconds as a raw number is accepted; copying '1h' vs '1 h' spacing differences; vendor docs quoting lease times in bare seconds.

Related errors


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