siyuan-note/siyuan · error
web search failed
Error message
web search failed: %s
What it means
WebSearch in kernel/util/websearch.go performs an Exa web-search request via httpclient. When the HTTP POST itself fails (transport-level error, not an HTTP error status), it wraps the underlying error into "web search failed: <err>" and returns it to the caller webSearchHandler.
Solutions
- Check basic network connectivity to the Exa endpoint from the machine running the kernel
- Inspect the wrapped cause after 'web search failed:' for DNS/timeout/TLS specifics
- Verify proxy environment variables (HTTP_PROXY/HTTPS_PROXY) are correct or unset as appropriate
- Ensure system CA certificates are installed and current
- Retry after connectivity is restored; the failure is transient in most network cases
Example fix
// before
if err != nil {
return "", errors.New("web search failed: " + err.Error())
}
// after: keep context and unwrap-able chain
if err != nil {
return "", fmt.Errorf("web search failed: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: probe connectivity before calling WebSearch
conn, err := net.DialTimeout("tcp", "api.exa.ai:443", 3*time.Second)
if err != nil { return fmt.Errorf("web search unavailable: %w", err) }
conn.Close() Try / catch
results, err := util.WebSearch(...)
if err != nil && strings.HasPrefix(err.Error(), "web search failed:") {
// inspect wrapped cause; retry with backoff or surface offline state
} Prevention
- Ensure outbound HTTPS to the search API is allowed by proxy/firewall
- Keep system CA certificates current
- Handle offline mode gracefully in UI before invoking search
When it happens
Trigger: Calling WebSearch when the network is down, DNS for the Exa endpoint fails, the request times out at the transport layer, TLS handshake fails, or a proxy misconfiguration blocks the outgoing POST.
Common situations: Offline or restricted environments, corporate proxies/firewalls blocking api.exa.ai, missing system CA certificates, IPv6/DNS issues in containers.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- authentication probe returned HTTP " + response.status
- boot progress request returned HTTP " + response.status
- discover OIDC provider failed
- download custom emoji failed
- download custom emoji failed with status
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/a652391171e3ab30.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/websearch.go:83
reqBody := mcpRequest{
JSONRPC: "2.0",
ID: 1,
Method: "tools/call",
Params: mcpParams{
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.", nilView on GitHub (pinned to 9f775e8a12)