{"record":{"id":"9f86f5f31d3cfd5d","repo":"fish2018/pansou","slug":"d-w-9f86f5","errorCode":null,"errorMessage":"重试 %d 次后仍然失败: %w","messagePattern":"重试 (.+?) 次后仍然失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/haisou/haisou.go","lineNumber":474,"sourceCode":"\t\t\tbackoff := time.Duration(1<<uint(i-1)) * 200 * time.Millisecond\n\t\t\ttime.Sleep(backoff)\n\t\t}\n\n\t\t// 克隆请求避免并发问题\n\t\treqClone := req.Clone(req.Context())\n\n\t\tresp, err := client.Do(reqClone)\n\t\tif err == nil && resp.StatusCode == 200 {\n\t\t\treturn resp, nil\n\t\t}\n\n\t\tif resp != nil {\n\t\t\tresp.Body.Close()\n\t\t}\n\t\tlastErr = err\n\t}\n\n\treturn nil, fmt.Errorf(\"重试 %d 次后仍然失败: %w\", maxRetries, lastErr)\n}\n\n// buildShareURL 根据平台类型和分享码构建完整的分享链接\nfunc buildShareURL(platform, shareCode string) string {\n\tswitch strings.ToLower(platform) {\n\tcase \"ali\":\n\t\treturn fmt.Sprintf(\"https://www.alipan.com/s/%s\", shareCode)\n\tcase \"baidu\":\n\t\treturn fmt.Sprintf(\"https://pan.baidu.com/s/%s\", shareCode)\n\tcase \"quark\":\n\t\treturn fmt.Sprintf(\"https://pan.quark.cn/s/%s\", shareCode)\n\tcase \"xunlei\":\n\t\treturn fmt.Sprintf(\"https://pan.xunlei.com/s/%s\", shareCode)\n\tcase \"tianyi\":\n\t\treturn fmt.Sprintf(\"https://cloud.189.cn/t/%s\", shareCode)\n\tdefault:\n\t\treturn \"\"\n\t}","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/haisou/haisou.go#L456-L492","documentation":"This error is returned by doRequestWithRetry after all retry attempts (maxRetries) for an HTTP request have failed. It wraps the last error encountered (lastErr), so the true root cause (timeout, connection refused, reset) is preserved. Callers fetchSearchPage and fetchShareLink surface it wrapped in their own request-failed errors.","triggerScenarios":"doRequestWithRetry exhausts maxRetries attempts, each returning a transport-level error (timeout, connection refused, TLS failure, connection reset), and returns this error with the final attempt's cause.","commonSituations":"Upstream haisou.cc fully unreachable/down; aggressive rate limiting dropping all attempts; wrong proxy configuration; DNS failures in the deployment environment; retry window too short during a transient outage.","solutions":["Inspect the wrapped lastErr to identify the root cause (timeout vs refused vs reset)","Increase maxRetries and add exponential backoff with jitter between attempts","Confirm upstream availability (curl/status page) and configure a proxy if the host is blocked in your network","Verify http.Client settings (Timeout, Transport, proxy env vars)","Fall back gracefully in callers — skip the pan/page instead of failing the whole search when retries are exhausted"],"exampleFix":"// before\nreturn nil, fmt.Errorf(\"重试 %d 次后仍然失败: %w\", maxRetries, lastErr)\n// after\nfor attempt := 1; attempt <= maxRetries; attempt++ {\n\tresp, err := client.Do(req)\n\tif err == nil {\n\t\treturn resp, nil\n\t}\n\tif resp != nil {\n\t\tresp.Body.Close()\n\t}\n\tlastErr = err\n\ttime.Sleep(backoffWithJitter(attempt)) // exponential backoff\n}\nreturn nil, fmt.Errorf(\"重试 %d 次后仍然失败: %w\", maxRetries, lastErr)","handlingStrategy":"retry","validationCode":"// pre-flight reachability probe\nconn, err := net.DialTimeout(\"tcp\", \"haisou.cc:443\", 5*time.Second)\nif err != nil {\n\treturn fmt.Errorf(\"upstream unreachable before request: %w\", err)\n}\nconn.Close()","typeGuard":null,"tryCatchPattern":"_, err := p.doRequestWithRetry(req, client)\nif err != nil {\n\tvar nerr net.Error\n\tif errors.As(err, &nerr) && nerr.Timeout() {\n\t\t// treat as upstream outage: back off longer before next attempt\n\t}\n\treturn fmt.Errorf(\"request failed after retries: %w\", err)\n}","preventionTips":["Use exponential backoff with jitter between attempts","Increase maxRetries modestly rather than hammering the upstream","Verify proxy/DNS configuration in deployment environments","Circuit-break and degrade gracefully when upstream is persistently down"],"tags":["network","retry","timeout","http","go"],"backgroundTag":"request-timeout","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"}