{"record":{"id":"3d8486df804199be","repo":"fish2018/pansou","slug":"s-d-w-3d8486","errorCode":null,"errorMessage":"[%s] 第%d页搜索请求失败: %w","messagePattern":"\\[(.+?)\\] 第(.+?)页搜索请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/xiaoyu/xiaoyu.go","lineNumber":158,"sourceCode":"\t}\n\n\treturn plugin.FilterResultsByKeyword(results, keyword), nil\n}\n\nfunc (p *XiaoyuPlugin) fetchPage(client *http.Client, keyword string, page int) (pageResult, error) {\n\trequestURL := fmt.Sprintf(searchURL, page, url.PathEscape(keyword))\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)\n\tif err != nil {\n\t\treturn pageResult{}, fmt.Errorf(\"[%s] 创建第%d页请求失败: %w\", p.Name(), page, err)\n\t}\n\tsetRequestHeaders(req)\n\n\tresp, err := doRequestWithRetry(client, req)\n\tif err != nil {\n\t\treturn pageResult{}, fmt.Errorf(\"[%s] 第%d页搜索请求失败: %w\", p.Name(), page, err)\n\t}\n\tdefer resp.Body.Close()\n\n\tdoc, err := goquery.NewDocumentFromReader(io.LimitReader(resp.Body, maxResponseSize))\n\tif err != nil {\n\t\treturn pageResult{}, fmt.Errorf(\"[%s] 第%d页解析失败: %w\", p.Name(), page, err)\n\t}\n\n\treturn parsePage(doc), nil\n}\n\nfunc setRequestHeaders(req *http.Request) {\n\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36\")\n\treq.Header.Set(\"Accept\", \"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\")\n\treq.Header.Set(\"Accept-Language\", \"zh-CN,zh;q=0.9,en;q=0.8\")\n\treq.Header.Set(\"Connection\", \"keep-alive\")\n\treq.Header.Set(\"Referer\", baseURL+\"/\")\n}","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/xiaoyu/xiaoyu.go#L140-L176","documentation":"fetchPage executes the search request through doRequestWithRetry, which retries non-200 responses and network errors. If all attempts fail, the last error is wrapped with the plugin name and page number. This is the terminal network-failure error for a page fetch.","triggerScenarios":"Every attempt in doRequestWithRetry failed: timeouts, connection refused/reset, TLS errors, or the site kept returning non-OK status codes (see error 819 for the non-200 cause).","commonSituations":"Site is down or rate-limiting your IP; aggressive retry loop triggered anti-bot blocking; proxy misconfigured; DNS failure in the deployment environment; page number beyond what the site supports.","solutions":["Inspect the wrapped cause (%w) to distinguish timeout/connection vs status-code failures.","Add backoff/jitter between retries and cap retry count to avoid triggering rate limits.","Rotate User-Agent / add delays if the site blocks scripted requests.","Verify network connectivity and proxy settings in the deployment environment."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if err := connectivityProbe(searchHost); err != nil {\n\treturn fmt.Errorf(\"network unreachable before search: %w\", err)\n}","typeGuard":"func isRetryableNetErr(err error) bool {\n\tvar ne net.Error\n\treturn errors.As(err, &ne) || errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.ECONNREFUSED)\n}","tryCatchPattern":"pr, err := fetchPage(page, keyword)\nif err != nil {\n\tvar ne net.Error\n\tif errors.As(err, &ne) && ne.Timeout() {\n\t\ttime.Sleep(2 * time.Second)\n\t\tpr, err = fetchPage(page, keyword)\n\t}\n\tif err != nil { return nil, err }\n}","preventionTips":["Use exponential backoff with jitter between retries to avoid tripping rate limits.","Distinguish timeouts from status failures by inspecting the wrapped cause.","Set explicit client Timeout and cap the retry count."],"tags":["network","http-request","retry","timeout"],"backgroundTag":"http-request-failed","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}