siyuan-note/siyuan · error

web search read response failed

Error message

web search read response failed: %s

What it means

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>".

Solutions

  1. Retry the search; body-read failures are usually transient network issues
  2. Check for connection resets or premature EOF in the wrapped error
  3. Reduce response size or increase timeouts if large responses routinely truncate
  4. Verify no proxy/firewall is cutting long-lived responses

Example fix

// before
if err != nil {
	return "", errors.New("web search read response failed: " + err.Error())
}
// after
if err != nil {
	return "", fmt.Errorf("web search read response failed: %w", err)
}
Defensive patterns

Strategy: retry

Try / catch

results, err := util.WebSearch(...)
if err != nil && strings.Contains(err.Error(), "read response failed") {
	// transient body-read failure; retry with backoff
}

Prevention

When it happens

Trigger: 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.

Common situations: Flaky mobile/network connections, long response bodies over unstable links, load balancers with aggressive idle timeouts.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/13885c22782996ca. Report an issue: GitHub.

Appendix: source

Thrown at kernel/util/websearch.go:89

			Name: "web_search_exa",
			Arguments: map[string]any{
				"query":      query,
				"type":       "auto",
				"numResults": 8,
				"livecrawl":  "fallback",
			},
		},
	}

	resp, err := httpclient.NewBrowserRequest().SetHeader("Accept", "application/json, text/event-stream").SetBody(reqBody).Post(exaURL)
	if err != nil {
		return "", errors.New("web search failed: " + err.Error())
	}
	defer resp.Body.Close()

	bodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", errors.New("web search read response failed: " + err.Error())
	}
	body := string(bodyBytes)

	preview := body
	if len(preview) > 500 {
		preview = body[:500]
	}
	logging.LogInfof("websearch response: status=%d, len=%d, preview=%s", resp.StatusCode, len(body), preview)

	text := parseMcpResponse(body)
	if text == "" {
		return "No search results found. Please try a different query.", nil
	}

	return truncateRunes(text, maxWebSearchChars), nil
}

func parseMcpResponse(body string) string {

View on GitHub (pinned to 9f775e8a12)