AdguardTeam/AdGuardHome · error

json duration is nil

Error message

json duration is nil

What it means

updConfMgr constructs a fresh configuration manager with configmgr.New(ctx, s.confMgrConf); if construction fails the error is wrapped as 'creating config manager'. This is the underlying cause surfaced by Refresh's 'updating configuration manager' error and points at config loading/validation problems rather than service startup.

Source

Thrown at internal/aghhttp/json.go:43

// type check
var _ json.Marshaler = JSONDuration(0)

// MarshalJSON implements the json.Marshaler interface for JSONDuration.  err is
// always nil.
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{}

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Look at the wrapped error from configmgr.New for the specific file/key at fault
  2. Validate the config file against the current version's schema (check docs/changelog for removed keys)
  3. Ensure the config path passed in confMgrConf exists and is readable by the service user
  4. Recreate or restore the config file from backup
Defensive patterns

Strategy: validation

Validate before calling

// Ensure config file is readable and parses before Refresh
if _, err := os.Stat(confPath); err != nil { return err }
if data, err := os.ReadFile(confPath); err != nil { return err } else if !yaml.IsV3Compatible(data) { /* validate */ }

Try / catch

if err := srv.updConfMgr(ctx); err != nil {
    return fmt.Errorf("config manager rebuild failed: %w", errors.Unwrap(err))
}

Prevention

When it happens

Trigger: Calling Refresh (which calls updConfMgr) when configmgr.New fails: unreadable/missing config file, schema-invalid YAML, or an environment (working directory, env vars) that makes config discovery fail.

Common situations: Config file deleted or renamed while the service runs; config contains keys removed in a newer version; the process's working directory changed so relative config paths break.

Related errors


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