siyuan-note/siyuan · error
stopped after 10 redirects
Error message
stopped after 10 redirects
What it means
The plugin server's HTTP client sets CheckRedirect to cap redirects at 10; when a request follows more than 10 hops, net/http aborts with this error, which surfaces as the request's failure. It protects against redirect loops on plugin-facing proxy/fetches.
Solutions
- Verify the target URL and fix the server-side redirect loop
- Use the final https:// URL directly instead of one that redirects
- Reduce redirect hops or contact the endpoint owner; the 10-hop limit is intentional
Example fix
// before
fetch('http://example.com/data'); // redirects back and forth
// after
fetch('https://example.com/data'); // direct final URL Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
try { const r = await client.get(url); } catch (e) { if (String(e).includes('stopped after 10 redirects')) { throw new Error('redirect loop at ' + url + '; use the final URL directly'); } throw e; } Prevention
- Link to final https URLs instead of redirecting shorteners
- Detect redirect loops on the target server side
- Keep authentication cookies consistent so auth redirects do not cycle
When it happens
Trigger: An outbound HTTP request from the plugin server (SSRF-safe transport) targets a URL whose server responds with a chain of more than 10 3xx redirects - typically a redirect loop or a very long redirect chain.
Common situations: Misconfigured target URL (http vs https ping-pong), auth-protected endpoints bouncing between login and original URL, or a looping short-link.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- authentication probe returned HTTP " + response.status
- boot progress request returned HTTP " + response.status
- Desktop OIDC login requires a loopback listener
- discover OIDC provider failed
- download custom emoji failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/43ab3ea22a4436c8.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/plugin/server.go:237
if !shouldProxyHeader(key, connectionHeaders) {
continue
}
dst.Del(key)
for _, value := range values {
dst.Add(key, value)
}
}
}
func newProxyHTTPClient() *http.Client {
return &http.Client{
Transport: &http.Transport{
DialContext: util.SSRFSafeDialer(30 * time.Second).DialContext,
DisableCompression: true,
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 10 {
return fmt.Errorf("stopped after 10 redirects")
}
req.Header.Del("Referer")
return nil
},
Timeout: 0,
}
}
func writeProxyResponse(c *gin.Context, proxy *ResponseProxy) {
if proxy.URL == "" {
c.String(http.StatusBadRequest, "missing proxy url")
return
}
targetURL, err := url.ParseRequestURI(proxy.URL)
if err != nil {
c.String(http.StatusBadRequest, "parse proxy url failed: %s", err.Error())
return
}View on GitHub (pinned to 9f775e8a12)