AdguardTeam/AdGuardHome · warning

parsing json time: %w

Error message

parsing json time: %w

What it means

The DNS settings PATCH handler (handlePatchSettingsDNS) tried to JSON-decode the request body into ReqPatchSettingsDNS and the decoder failed. This is a client-side malformed request: invalid JSON syntax, wrong types for fields, or an empty/truncated body. The server responds via aghhttp.WriteJSONResponseError with a 4xx-class error.

Source

Thrown at internal/aghhttp/json.go:48

func (d JSONDuration) MarshalJSON() (b []byte, err error) {
	msec := float64(time.Duration(d)) / nsecPerMsec
	b = strconv.AppendFloat(nil, msec, 'f', -1, 64)

	return b, nil
}

// type check
var _ json.Unmarshaler = (*JSONDuration)(nil)

// UnmarshalJSON implements the json.Marshaler interface for *JSONDuration.
func (d *JSONDuration) UnmarshalJSON(b []byte) (err error) {
	if d == nil {
		return fmt.Errorf("json duration is nil")
	}

	msec, err := strconv.ParseFloat(string(b), 64)
	if err != nil {
		return fmt.Errorf("parsing json time: %w", err)
	}

	*d = JSONDuration(int64(msec * nsecPerMsec))

	return nil
}

// JSONTime is a time.Time that can be decoded from JSON and encoded into JSON
// according to our API conventions.
type JSONTime time.Time

// type check
var _ json.Marshaler = JSONTime{}

// MarshalJSON implements the json.Marshaler interface for JSONTime.  err is
// always nil.
func (t JSONTime) MarshalJSON() (b []byte, err error) {
	msec := float64(time.Time(t).UnixNano()) / nsecPerMsec

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Validate the JSON body with jq or a linter before sending
  2. Match field names and types to the ReqPatchSettingsDNS struct (check the API docs/struct definition)
  3. Set Content-Type: application/json and ensure the body is fully transmitted
  4. Use the official client/UI rather than raw requests

Example fix

// before
curl -X PATCH http://host/control/dns_config -d '{"dnssec_enabled": "yes"}'
// after
curl -X PATCH http://host/control/dns_config \
  -H 'Content-Type: application/json' \
  -d '{"dnssec_enabled": true}'
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: validate JSON before sending
var req map[string]any
if err := json.Unmarshal(body, &req); err != nil { return err }

Type guard

func isValidPatchDNS(body []byte) bool {
    var r ReqPatchSettingsDNS
    return json.Unmarshal(body, &r) == nil
}

Try / catch

resp, err := client.Patch(url, body)
if err == nil && resp.StatusCode >= 400 {
    // read aghhttp error payload; decode errors are client-fixable
}

Prevention

When it happens

Trigger: PATCH /control/dns_config (or equivalent settings endpoint) with a body that is not valid JSON, has wrong field types (e.g. a string where a bool is expected), or is empty/truncated.

Common situations: Hand-crafting curl requests with quoting mistakes; a client library serializing optional fields incorrectly; sending Content-Length larger than the actual body so decoding hits EOF.

Related errors


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