AdguardTeam/AdGuardHome · error

json time is nil

Error message

json time is nil

What it means

The DNS PATCH handler successfully decoded the request and applied the requested fields to a copy of the current DNS config, but confMgr.UpdateDNS rejected the resulting configuration. The wrapped error describes which DNS setting was invalid (upstream servers, bootstrap DNS, listening addresses, etc.).

Source

Thrown at internal/aghhttp/json.go:78

// 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
	b = strconv.AppendFloat(nil, msec, 'f', -1, 64)

	return b, nil
}

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

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

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

	*t = JSONTime(time.Unix(0, int64(msec*nsecPerMsec)).UTC())

	return nil
}

// WriteJSONResponse writes headers with the code, encodes resp into w, and logs
// any errors it encounters.  r is used to get additional information from the
// request.  l, w, and r must not be nil.
func WriteJSONResponse(
	ctx context.Context,
	l *slog.Logger,

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Read the wrapped error from UpdateDNS — it names the offending field/value
  2. Fix the specific DNS setting (upstream URL format, listen address syntax) and retry the PATCH
  3. GET the current DNS config first, validate the merged result locally, then PATCH
  4. Consult the DNS configuration docs for accepted upstream URL formats

Example fix

// before
{"upstream_dns": ["8.8.8.8"]}
// after
{"upstream_dns": ["8.8.8.8:53"]} // or "https://dns.google/dns-query"
Defensive patterns

Strategy: validation

Validate before calling

// GET current config, merge, validate upstream formats client-side
if !validUpstreamURL(u) { return fmt.Errorf("bad upstream %q", u) }

Type guard

func validUpstreamURL(s string) bool {
    _, err := url.Parse(s)
    return err == nil && (strings.Contains(s, "://") || net.ParseIP(s) != nil || isHostPort(s))
}

Try / catch

if err := updateDNS(cfg); err != nil {
    if strings.Contains(err.Error(), "updating:") {
        // field-level validation issue; fix named field and retry
    }
}

Prevention

When it happens

Trigger: PATCHing DNS settings where the merged configuration is invalid: malformed upstream DNS URLs, invalid listen addresses, bad bootstrap values, or an invalid upstream mode.

Common situations: Typo in an upstream DNS server URL (missing dns:// scheme or port); setting an empty upstream list; combining incompatible DNS options; a partial PATCH interacting badly with existing config values.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


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