{"record":{"id":"f6a5911469709c8e","repo":"fish2018/pansou","slug":"s-w-f6a591","errorCode":null,"errorMessage":"[%s] 搜索请求失败: %w","messagePattern":"\\[(.+?)\\] 搜索请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/ahhhhfs/ahhhhfs.go","lineNumber":181,"sourceCode":"\t// 3. 创建请求\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建请求失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 4. 设置完整的请求头（避免反爬虫）\n\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.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(\"Upgrade-Insecure-Requests\", \"1\")\n\treq.Header.Set(\"Cache-Control\", \"max-age=0\")\n\treq.Header.Set(\"Referer\", \"https://www.ahhhhfs.com/\")\n\t\n\t// 5. 发送请求（带重试机制）\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\t\n\t// 6. 解析搜索结果页面\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析搜索页面失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 7. 提取搜索结果\n\tvar results []model.SearchResult\n\tvar wg sync.WaitGroup\n\tvar mu sync.Mutex\n\tsemaphore := make(chan struct{}, MaxConcurrency)","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/ahhhhfs/ahhhhfs.go#L163-L199","documentation":"searchImpl wraps any error from p.doRequestWithRetry(req, client) — the actual GET round trip to ahhhhfs.com including its built-in retries — as '[%s] 搜索请求失败'. All transport-level failures (DNS, TCP, TLS, proxy errors, timeouts from DefaultTimeout, and retries exhausted) surface here. Because retries are already applied, an error here means the request failed persistently.","triggerScenarios":"doRequestWithRetry returns err after exhausting its retry attempts: DNS resolution failure for www.ahhhhfs.com, connection refused/reset, TLS handshake failure, context deadline exceeded (DefaultTimeout), or proxy misconfiguration — all persisting across retries.","commonSituations":"The site (or its CDN) blocks the host's IP or region; the machine has no/broken internet or DNS; DefaultTimeout is too short for the site's response time; a required proxy is not configured; the domain changed and the old one no longer resolves.","solutions":["Read the wrapped %w error to distinguish timeout (context deadline exceeded) from connect/DNS failures.","Verify reachability with curl -v 'https://www.ahhhhfs.com/' from the same host.","If the site requires a proxy on this network, configure it on the http.Client's Transport.","Increase DefaultTimeout if requests are consistently timing out near the limit.","Check whether doRequestWithRetry's retry count/backoff is adequate; harden it against connection resets."],"exampleFix":"// before\nresp, err := p.doRequestWithRetry(req, client)\nif err != nil {\n    return nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n}\n// after\nresp, err := p.doRequestWithRetry(req, client)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        return nil, fmt.Errorf(\"[%s] 搜索请求超时(>%s): %w\", p.Name(), DefaultTimeout, err)\n    }\n    return nil, fmt.Errorf(\"[%s] 搜索请求失败(重试后仍失败): %w\", p.Name(), err)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"results, err := p.Search(ctx, keyword)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        // 超时: 增大 DefaultTimeout 或减少并发后重试\n    } else {\n        // 网络/代理故障: 换网络或配置代理后重试\n    }\n}","preventionTips":["Give DefaultTimeout headroom for the site's typical latency.","Configure the http.Client proxy when the network requires one.","Rely on doRequestWithRetry but verify its retry count/backoff suits transient failures.","Confirm the site domain is current and reachable from your host."],"tags":["go","http","network","retry"],"backgroundTag":"network-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"}