fish2018/pansou · error
detail request failed
Error message
detail request failed: %w
What it means
Wrapped network error in DiscourseAsyncPlugin.GetTopicDetail (plugin/discourse/discourse.go:477): the cloudscraper GET to the topic detail URL failed before any response was produced (DNS, TLS, timeout, or anti-bot challenge failure). No HTTP status exists at this point, so upstream code cannot retry with status-based logic from this error alone.
Solutions
- Check the wrapped error to identify DNS/connect/TLS cause
- Verify the site URL is correct and reachable in a browser
- Confirm cloudscraper solved the Cloudflare challenge (403/503 with cf pages)
- Check proxy/VPN and firewall settings
- Retry on transient network errors with backoff
Defensive patterns
Strategy: retry
Validate before calling
u, err := url.Parse(detailURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid detail url: %q", detailURL)
} Try / catch
links, err := plugin.GetTopicDetail(id)
if err != nil && strings.Contains(err.Error(), "detail request failed") {
var nerr net.Error
if errors.As(errors.Unwrap(err), &nerr) && nerr.Timeout() {
time.Sleep(backoff)
links, err = plugin.GetTopicDetail(id)
}
} Prevention
- Verify site reachability before batch fetching
- Use sane timeouts and retry with backoff for transient failures
- Keep proxy configuration correct
When it happens
Trigger: p.scraper.Get(detailURL) returns a non-nil error — DNS failure, connection refused/reset, timeout, TLS error, or cloudflare bypass failure.
Common situations: 目标站点不可达、本地网络断开、代理配置错误。
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
- [ ] search request failed on page
- [ ] unexpected status code: on page
- [ ] read response failed on page
- unexpected status code
- read response failed
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/8426c9072c0810fb.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/discourse/discourse.go:477
}
return content
}
// GetTopicDetail 获取主题详情(可选实现,用于获取完整链接)
func (p *DiscourseAsyncPlugin) GetTopicDetail(topicID int) ([]model.Link, error) {
// 检查 cloudscraper 是否初始化成功
if p.scraper == nil {
return nil, fmt.Errorf("cloudscraper not initialized")
}
// 构建详情URL
detailURL := fmt.Sprintf(detailURLTemplate, topicID)
// 发送详情请求
resp, err := p.scraper.Get(detailURL)
if err != nil {
return nil, fmt.Errorf("detail request failed: %w", err)
}
defer resp.Body.Close()
// 检查HTTP状态码
if resp.StatusCode != 200 {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read response failed: %w", err)
}
// 解析JSON响应
var detailResp DetailResponse
if err := json.Unmarshal(body, &detailResp); err != nil {
return nil, fmt.Errorf("parse json failed: %w", err)View on GitHub (pinned to beaa561337)