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
- Read the wrapped error from UpdateDNS — it names the offending field/value
- Fix the specific DNS setting (upstream URL format, listen address syntax) and retry the PATCH
- GET the current DNS config first, validate the merged result locally, then PATCH
- 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
- Fetch and merge current config before PATCHing
- Follow documented upstream DNS URL formats
- Dry-run validation of DNS settings in the UI first
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
- parsing json time: %w
- interface %s has no ipv6 addresses
- invalid ip version %d
- interface %s has no ipv4 addresses
- could not find hardware port for %s
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/f60fd868fd46d631.
Report an issue: GitHub.