{"record":{"id":"610283b1f000417a","repo":"siyuan-note/siyuan","slug":"failed-to-read-response-body-w","errorCode":null,"errorMessage":"failed to read response body: %w","messagePattern":"failed to read response body: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_client.go","lineNumber":141,"sourceCode":"\t\t\t\t}\n\t\t\t\tr.SetHeader(model.XAuthTokenKey, p.token)\n\n\t\t\t\tif bodyString != nil {\n\t\t\t\t\tr.SetBody(*bodyString)\n\t\t\t\t} else if bodyBytes != nil {\n\t\t\t\t\tr.SetBody(*bodyBytes)\n\t\t\t\t}\n\n\t\t\t\tresp, sendErr := r.Send(method, targetURL)\n\t\t\t\tif sendErr != nil {\n\t\t\t\t\terr = sendErr\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tdefer resp.Body.Close()\n\t\t\t\tbody, readErr := io.ReadAll(resp.Body)\n\t\t\t\tif readErr != nil {\n\t\t\t\t\terr = fmt.Errorf(\"failed to read response body: %w\", readErr)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tresponseHeader := map[string]string{}\n\t\t\t\tfor k, vs := range resp.Header {\n\t\t\t\t\tresponseHeader[k] = strings.Join(vs, \", \")\n\t\t\t\t}\n\n\t\t\t\trunErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {\n\t\t\t\t\tresponse := rt.NewObject()\n\t\t\t\t\tlo.Must0(response.Set(\"url\", rt.ToValue(path)))\n\t\t\t\t\tlo.Must0(response.Set(\"ok\", rt.ToValue(resp.StatusCode >= 200 && resp.StatusCode < 300)))\n\t\t\t\t\tlo.Must0(response.Set(\"status\", rt.ToValue(resp.StatusCode)))\n\t\t\t\t\tlo.Must0(response.Set(\"statusText\", rt.ToValue(resp.Status)))\n\t\t\t\t\tlo.Must0(response.Set(\"headers\", rt.ToValue(responseHeader)))\n\t\t\t\t\tlo.Must0(ObjectSetDataMethods(p, rt, response, body))\n\t\t\t\t\tresult = response\n\t\t\t\t\treturn","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_client.go#L123-L159","documentation":"io.ReadAll returned an error while consuming the HTTP response body in siyuan.client.fetch. The %w wraps the underlying read error. The request was sent and a response started, but the body stream broke before it could be fully read.","triggerScenarios":"The kernel closed/reset the loopback connection mid-response, the local server shut down during a streaming or large response, or the underlying TCP connection was dropped.","commonSituations":"Kernel restart during a plugin request, very large responses timing out, or the OS closing the loopback socket under resource pressure.","solutions":["Retry the request once — transient body-read failures usually succeed on retry.","Verify the kernel is still running (check the ServerPort health endpoint) before retrying.","For large payloads, reduce response size or paginate to lower the chance of a mid-stream break."],"exampleFix":"async function fetchRetry(path, init, tries = 2) {\n  for (let i = 0; i < tries; i++) {\n    try { return await siyuan.client.fetch(path, init); }\n    catch (e) { if (i === tries - 1) throw e; }\n  }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const res = await siyuan.client.fetch('/api/x');\n} catch (e) {\n  if (/failed to read response body/.test(String(e))) {\n    // retry — transient mid-stream break\n  }\n}","preventionTips":["Wrap fetches used for bulk data in a retry helper.","Don't keep responses open longer than needed.","Watch kernel uptime if these errors cluster."],"tags":["client-fetch","network","response-body","retry"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}