{"record":{"id":"847eff19918d29ff","repo":"fish2018/pansou","slug":"s-hsid-s-w-847eff","errorCode":null,"errorMessage":"[%s] hsid=%s链接请求失败: %w","messagePattern":"\\[(.+?)\\] hsid=(.+?)链接请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/haisou/haisou.go","lineNumber":403,"sourceCode":"\tdefer cancel()\n\n\t// 创建请求对象\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", fetchURL, nil)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s创建链接请求失败: %w\", p.Name(), hsid, err)\n\t}\n\n\t// 设置请求头\n\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\")\n\treq.Header.Set(\"Accept\", \"application/json, text/plain, */*\")\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\", \"https://haisou.cc/\")\n\n\t// 发送HTTP请求（带重试机制）\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接请求失败: %w\", p.Name(), hsid, err)\n\t}\n\tdefer resp.Body.Close()\n\n\t// 检查状态码\n\tif resp.StatusCode != 200 {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接请求返回状态码: %d\", p.Name(), hsid, resp.StatusCode)\n\t}\n\n\t// 读取响应体\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s读取响应失败: %w\", p.Name(), hsid, err)\n\t}\n\n\t// 解析响应\n\tvar apiResp FetchAPIResponse\n\tif err := json.Unmarshal(body, &apiResp); err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接JSON解析失败: %w\", p.Name(), hsid, err)","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/haisou/haisou.go#L385-L421","documentation":"This error is thrown by fetchShareLink when the share-link HTTP request fails after the plugin's built-in retries (p.doRequestWithRetry), e.g. connection errors, TLS failures, DNS failures, or context timeout. The wrapped err carries the retry exhaustion message ('重试 %d 次后仍然失败') from doRequestWithRetry.","triggerScenarios":"p.doRequestWithRetry(req, client) returns a non-nil error inside fetchShareLink — the GET to the haisou fetch API failed on every retry attempt (network unreachable, timeout after 15s, TLS handshake failure, connection reset).","commonSituations":"haisou.cc is down or blocked by firewall/GFW; server or corporate proxy blocking outbound HTTPS; 15s timeout too short for a slow network; rate limiting causing connection resets; DNS resolution failures in containers.","solutions":["Run curl https://haisou.cc/ from the same host to confirm connectivity","Check whether the host needs a proxy (set HTTP(S)_PROXY or configure the http.Client Transport)","Increase the 15-second timeout and/or maxRetries in doRequestWithRetry","Inspect the wrapped error from doRequestWithRetry to distinguish timeout vs connection refused vs TLS","Verify DNS resolution inside your deployment environment (docker/container networks)."],"exampleFix":"// before\nresp, err := p.doRequestWithRetry(req, client)\nif err != nil {\n\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接请求失败: %w\", p.Name(), hsid, err)\n}\n// after\nresp, err := p.doRequestWithRetry(req, client)\nif err != nil {\n\tvar netErr net.Error\n\tif errors.As(err, &netErr) && netErr.Timeout() {\n\t\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接请求超时(15s)，可考虑增大超时或稍后重试: %w\", p.Name(), hsid, err)\n\t}\n\treturn \"\", \"\", fmt.Errorf(\"[%s] hsid=%s链接请求失败: %w\", p.Name(), hsid, err)\n}","handlingStrategy":"retry","validationCode":"// pre-flight connectivity check\nresp, err := http.Head(\"https://haisou.cc/\")\nif err != nil {\n\treturn fmt.Errorf(\"upstream unreachable: %w\", err)\n}\nresp.Body.Close()","typeGuard":null,"tryCatchPattern":"resp, err := p.doRequestWithRetry(req, client)\nif err != nil {\n\tvar nerr net.Error\n\tif errors.As(err, &nerr) && nerr.Timeout() {\n\t\t// schedule retry with backoff\n\t}\n\treturn fmt.Errorf(\"share link request failed: %w\", err)\n}\ndefer resp.Body.Close()","preventionTips":["Configure proxy env vars if haisou.cc is blocked in your network","Keep timeouts generous (>=15s) for slow upstreams","Monitor upstream availability and circuit-break when it's down","Rely on the plugin's built-in retry instead of stacking extra retries blindly"],"tags":["network","http","timeout","retry","go"],"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"}