siyuan-note/siyuan · error
request failed:
Error message
request failed:
What it means
ssrfSafeClient.Do executes the request; any transport-level failure (DNS, TCP connect, TLS, timeout, proxy failure, context cancel) is wrapped as 'request failed: <cause>'. The inner error text names the actual cause, so it should be read, not discarded.
Source
Thrown at kernel/util/httprequest.go:335
if method == "" {
method = "GET"
}
var reqBody io.Reader
if body != "" && method != "GET" && method != "HEAD" {
reqBody = strings.NewReader(body)
}
req, err := http.NewRequest(method, rawURL, reqBody)
if err != nil {
return 0, "", "", errors.New("invalid request: " + err.Error())
}
for k, v := range headers {
req.Header.Set(k, v)
}
resp, err := ssrfSafeClient.Do(req)
if err != nil {
return 0, "", "", errors.New("request failed: " + err.Error())
}
if resp == nil {
return 0, "", "", errors.New("nil response")
}
defer resp.Body.Close()
statusCode = resp.StatusCode
contentType = resp.Header.Get("Content-Type")
maxReadBytes := int64(maxHTTPRequestBytes)
if !isTextContentType(contentType) {
maxReadBytes = maxHTTPRequestFileBytes
}
// ContentLength 为 -1(chunked)时跳过大小预检,交由 LimitReader 兜底截断。
if resp.ContentLength > maxReadBytes {
return statusCode, contentType, "", errors.New("response too large")
}
View on GitHub (pinned to 8641553a1f)
Solutions
- Read the wrapped cause: 'connection refused' → service/port wrong; 'no such host' → DNS; 'certificate is valid for' → TLS/SNI problem; 'context deadline exceeded' → raise timeout
- Verify the service is up and reachable with `curl -v <url>` from the same machine
- Fix TLS issues (valid cert) rather than disabling verification
- Add retry with backoff for transient network errors and a sane timeout on the context
Example fix
// before
HTTPRequest("GET", "https://api.example.com:9999/v1", nil, "") // wrong port, connection refused
// after
HTTPRequest("GET", "https://api.example.com:443/v1", nil, "") Defensive patterns
Strategy: try-catch
Validate before calling
if u, err := url.Parse(rawURL); err != nil || u.Host == "" || (u.Scheme != "http" && u.Scheme != "https") {
return errors.New("URL must be an absolute http(s) URL")
} Try / catch
status, _, _, err := HTTPRequest("GET", url, nil, "")
if err != nil {
if strings.HasPrefix(err.Error(), "request failed: ") && isTransient(err) {
time.Sleep(backoff)
return HTTPRequest("GET", url, nil, "") // retry once
}
return err
} Prevention
- Set a realistic context timeout before issuing requests
- Classify the wrapped cause (DNS vs connect vs TLS vs timeout) before reacting
- Retry with backoff only for transient causes (timeouts, connection reset)
- Validate target reachability with curl -v when debugging persistent failures
When it happens
Trigger: HTTPRequest called against a host that is unreachable, refuses connections, has bad TLS, or where the context deadline expires during Do; also failures inside the SSRF-safe transport's proxy tunnel.
Common situations: Target server down or wrong port; TLS certificate invalid/expired/self-signed; firewall dropping outbound traffic; request timeout too small; proxy misconfiguration surfacing here after passing the earlier checks.
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
- stopped after 10 redirects
- fetch failed: %s
- read body failed: %s
- host has no public IP:
- version request returned HTTP " + response.status
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4a647dc871b0596f.
Report an issue: GitHub.