{"record":{"id":"abffefc1ab6a2b6d","repo":"jeessy2/ddns-go","slug":"w","errorCode":null,"errorMessage":"序列化请求体失败: %w","messagePattern":"序列化请求体失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dns/hipmdnsmgr.go","lineNumber":196,"sourceCode":"// 参考 dnsmgr.ts 中的 request<T>() 方法\nfunc (h *HiPMDnsMgr) request(baseURL, apiToken, method, path string, body interface{}) (*DnsMgrApiResponse, error) {\n\t// 参考 dnsmgr.ts 中的 URL 处理方式\n\t// Ensure baseUrl doesn't end with /api and path starts with /\n\tbase := strings.TrimSuffix(baseURL, \"/\")\n\tbase = strings.TrimSuffix(base, \"/api\")\n\n\tnormalizedPath := path\n\tif !strings.HasPrefix(normalizedPath, \"/\") {\n\t\tnormalizedPath = \"/\" + normalizedPath\n\t}\n\n\turl := base + \"/api\" + normalizedPath\n\n\tvar bodyReader *bytes.Buffer\n\tif body != nil {\n\t\tjsonBody, err := json.Marshal(body)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"序列化请求体失败: %w\", err)\n\t\t}\n\t\tbodyReader = bytes.NewBuffer(jsonBody)\n\t} else {\n\t\tbodyReader = bytes.NewBuffer(nil)\n\t}\n\n\treq, err := http.NewRequest(method, url, bodyReader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// 设置请求头\n\theaders := h.getHeaders(apiToken)\n\tfor key, value := range headers {\n\t\treq.Header.Set(key, value)\n\t}\n\n\tresp, err := h.httpClient.Do(req)","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/dns/hipmdnsmgr.go#L178-L214","documentation":"request() fails to json.Marshal the request body before sending it to the DNSMgr API. With the current callers the body is a map[string]interface{} of plain strings/ints, which is always marshalable in practice, so this error indicates a non-marshalable value reached request() (channels, funcs, invalid types) — typically after a code modification.","triggerScenarios":"Calling createRecord/updateExistingRecord (via request) with a body containing a value that encoding/json cannot marshal: e.g. a channel, function, or cyclic/unsupported type placed into the body map.","commonSituations":"Developer adds a new field to the request body with a custom type lacking json marshaling, or passes a struct with unexported-only/unsupported fields; never occurs with stock string/int map bodies in normal operation.","solutions":["Inspect the wrapped %w cause — it names the unsupported json type","Ensure every value in the request body map is a JSON-marshalable type (string, int, bool, slices, maps, tagged structs)","Add json.Marshaler or proper struct tags for custom types","If TTL came from config, confirm strconv.Atoi parsing didn't inject odd values (stock code defaults to 600 anyway)"],"exampleFix":"// before\nbody := map[string]interface{}{\"callback\": func(r *http.Request) {}} // unmarshalable\n// after\nbody := map[string]interface{}{\"name\": name, \"type\": recordType, \"value\": value, \"ttl\": ttl, \"line\": \"0\"}","handlingStrategy":"validation","validationCode":"// guard before passing a body to any low-level request\nfunc ensureMarshalable(body interface{}) error {\n    if body == nil {\n        return nil\n    }\n    _, err := json.Marshal(body)\n    return err // surfaces unmarshalable types before the HTTP call\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only put JSON-native values (string, int, bool, slices, maps) in request bodies","Avoid channels, funcs, or untagged custom structs in body maps","Write a table test that marshals every request-body shape the provider builds"],"tags":["go","json","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"5874c2e6667c69357ab95079421131104bd3fcae","analyzedAt":"2026-09-03T15:41:16.799Z","contentChangedAt":"2026-09-03T15:41:16.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}