{"record":{"id":"13885c22782996ca","repo":"siyuan-note/siyuan","slug":"web-search-read-response-failed-s","errorCode":null,"errorMessage":"web search read response failed: %s","messagePattern":"web search read response failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/websearch.go","lineNumber":89,"sourceCode":"\t\t\tName: \"web_search_exa\",\n\t\t\tArguments: map[string]any{\n\t\t\t\t\"query\":      query,\n\t\t\t\t\"type\":       \"auto\",\n\t\t\t\t\"numResults\": 8,\n\t\t\t\t\"livecrawl\":  \"fallback\",\n\t\t\t},\n\t\t},\n\t}\n\n\tresp, err := httpclient.NewBrowserRequest().SetHeader(\"Accept\", \"application/json, text/event-stream\").SetBody(reqBody).Post(exaURL)\n\tif err != nil {\n\t\treturn \"\", errors.New(\"web search failed: \" + err.Error())\n\t}\n\tdefer resp.Body.Close()\n\n\tbodyBytes, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", errors.New(\"web search read response failed: \" + err.Error())\n\t}\n\tbody := string(bodyBytes)\n\n\tpreview := body\n\tif len(preview) > 500 {\n\t\tpreview = body[:500]\n\t}\n\tlogging.LogInfof(\"websearch response: status=%d, len=%d, preview=%s\", resp.StatusCode, len(body), preview)\n\n\ttext := parseMcpResponse(body)\n\tif text == \"\" {\n\t\treturn \"No search results found. Please try a different query.\", nil\n\t}\n\n\treturn truncateRunes(text, maxWebSearchChars), nil\n}\n\nfunc parseMcpResponse(body string) string {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/websearch.go#L71-L107","documentation":"WebSearch reads the full Exa response body with io.ReadAll after a successful POST. If reading the body fails (connection reset mid-body, premature EOF, context cancellation), the function returns \"web search read response failed: <err>\".","triggerScenarios":"The server closes the connection before the body completes, the client cancels the request mid-read, or an intermediate proxy truncates the streamed (SSE-style) response.","commonSituations":"Flaky mobile/network connections, long response bodies over unstable links, load balancers with aggressive idle timeouts.","solutions":["Retry the search; body-read failures are usually transient network issues","Check for connection resets or premature EOF in the wrapped error","Reduce response size or increase timeouts if large responses routinely truncate","Verify no proxy/firewall is cutting long-lived responses"],"exampleFix":"// before\nif err != nil {\n\treturn \"\", errors.New(\"web search read response failed: \" + err.Error())\n}\n// after\nif err != nil {\n\treturn \"\", fmt.Errorf(\"web search read response failed: %w\", err)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"results, err := util.WebSearch(...)\nif err != nil && strings.Contains(err.Error(), \"read response failed\") {\n\t// transient body-read failure; retry with backoff\n}","preventionTips":["Retry transient IO errors with exponential backoff","Avoid cancelling requests mid-body unless necessary","Check proxy/load-balancer idle timeouts for long responses"],"tags":["network","io","http"],"backgroundTag":"network-request-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}