{"record":{"id":"23ab86293f3c2214","repo":"jeessy2/ddns-go","slug":"v-23ab86","errorCode":null,"errorMessage":"读取响应失败: %v","messagePattern":"读取响应失败: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dns/nowcn.go","lineNumber":268,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"创建请求失败: %v\", err)\n\t}\n\n\t// 设置请求头\n\treq.Header.Set(\"Accept\", \"application/json\")\n\n\t// 发送请求\n\tclient := t.httpClient\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"请求失败: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\t// 读取响应\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"读取响应失败: %v\", err)\n\t}\n\n\t// 检查HTTP状态码\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"API请求失败，状态码: %d, 响应: %s\", resp.StatusCode, string(body))\n\t}\n\n\treturn body, nil\n}\n","sourceCodeStart":250,"sourceCodeEnd":278,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/dns/nowcn.go#L250-L278","documentation":"dns/nowcn.go wraps the io.ReadAll(resp.Body) failure that occurs inside the shared request() helper (used by create, modify, getRecordList). It means the Nowcn API responded but the response body could not be read, usually because the connection dropped mid-response. The underlying io error is embedded in the message with %v.","triggerScenarios":"Any Nowcn API call (create, modify, getRecordList) where the HTTP response body read fails: server closes the connection early, network timeout during body transfer, or TLS interruption while streaming the body.","commonSituations":"Flaky networks or VPNs between the client and the Nowcn API; server-side gateways closing keep-alive connections; very short read timeouts; proxies that terminate responses prematurely.","solutions":["Retry the request; transient connection resets usually succeed on a second attempt","Check network connectivity/proxy stability between the host and the Nowcn API","Inspect the wrapped %v error to distinguish timeout vs connection reset","Ensure the configured HTTP client has a sane timeout and retry policy"],"exampleFix":"// before\nbody, err := io.ReadAll(resp.Body)\nif err != nil {\n\treturn nil, fmt.Errorf(\"读取响应失败: %v\", err)\n}\n// after (caller-side retry)\nfor i := 0; i < 3; i++ {\n\tbody, err := provider.getRecordList(domain)\n\tif err == nil {\n\t\tbreak\n\t}\n\tif strings.Contains(err.Error(), \"读取响应失败\") {\n\t\ttime.Sleep(time.Duration(i+1) * time.Second)\n\t\tcontinue\n\t}\n\treturn err\n}","handlingStrategy":"retry","validationCode":"// preflight connectivity check\nif _, err := http.Head(\"https://www.now.cn\"); err != nil {\n\treturn fmt.Errorf(\"nowcn unreachable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// Go: sentinel check + bounded retry\nfor i := 0; i < 3; i++ {\n\trecs, err := provider.getRecordList(domain)\n\tif err == nil {\n\t\treturn recs, nil\n\t}\n\tif !strings.Contains(err.Error(), \"读取响应失败\") {\n\t\treturn nil, err\n\t}\n\ttime.Sleep(time.Duration(1<<i) * time.Second)\n}\nreturn nil, err","preventionTips":["Run DDNS updates on a stable connection; add retry with exponential backoff","Set a generous but bounded HTTP client timeout","Monitor network health before scheduled updates"],"tags":["network","io","http-response"],"backgroundTag":"response-body-read-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"}