{"record":{"id":"a9ded110ed45dd78","repo":"AdguardTeam/AdGuardHome","slug":"parsing-json-time-w","errorCode":null,"errorMessage":"parsing json time: %w","messagePattern":"parsing json time: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/aghhttp/json.go","lineNumber":48,"sourceCode":"func (d JSONDuration) MarshalJSON() (b []byte, err error) {\n\tmsec := float64(time.Duration(d)) / nsecPerMsec\n\tb = strconv.AppendFloat(nil, msec, 'f', -1, 64)\n\n\treturn b, nil\n}\n\n// type check\nvar _ json.Unmarshaler = (*JSONDuration)(nil)\n\n// UnmarshalJSON implements the json.Marshaler interface for *JSONDuration.\nfunc (d *JSONDuration) UnmarshalJSON(b []byte) (err error) {\n\tif d == nil {\n\t\treturn fmt.Errorf(\"json duration is nil\")\n\t}\n\n\tmsec, err := strconv.ParseFloat(string(b), 64)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"parsing json time: %w\", err)\n\t}\n\n\t*d = JSONDuration(int64(msec * nsecPerMsec))\n\n\treturn nil\n}\n\n// JSONTime is a time.Time that can be decoded from JSON and encoded into JSON\n// according to our API conventions.\ntype JSONTime time.Time\n\n// type check\nvar _ json.Marshaler = JSONTime{}\n\n// MarshalJSON implements the json.Marshaler interface for JSONTime.  err is\n// always nil.\nfunc (t JSONTime) MarshalJSON() (b []byte, err error) {\n\tmsec := float64(time.Time(t).UnixNano()) / nsecPerMsec","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/aghhttp/json.go#L30-L66","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Validate the JSON body with jq or a linter before sending","Match field names and types to the ReqPatchSettingsDNS struct (check the API docs/struct definition)","Set Content-Type: application/json and ensure the body is fully transmitted","Use the official client/UI rather than raw requests"],"exampleFix":"// before\ncurl -X PATCH http://host/control/dns_config -d '{\"dnssec_enabled\": \"yes\"}'\n// after\ncurl -X PATCH http://host/control/dns_config \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"dnssec_enabled\": true}'","handlingStrategy":"validation","validationCode":"// Client-side: validate JSON before sending\nvar req map[string]any\nif err := json.Unmarshal(body, &req); err != nil { return err }","typeGuard":"func isValidPatchDNS(body []byte) bool {\n    var r ReqPatchSettingsDNS\n    return json.Unmarshal(body, &r) == nil\n}","tryCatchPattern":"resp, err := client.Patch(url, body)\nif err == nil && resp.StatusCode >= 400 {\n    // read aghhttp error payload; decode errors are client-fixable\n}","preventionTips":["Always set Content-Type: application/json","Validate payloads with jq or struct marshalling before send","Write integration tests for API clients against a local instance"],"tags":["http","json","dns","request-validation","go"],"backgroundTag":"json-decode-failed","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}