{"record":{"id":"ecdb3f840f3bbd14","repo":"fish2018/pansou","slug":"w-ecdb3f","errorCode":null,"errorMessage":"请求失败: %w","messagePattern":"请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/pan666/pan666.go","lineNumber":207,"sourceCode":"\treq.Header.Set(\"User-Agent\", getRandomUA())\n\treq.Header.Set(\"X-Forwarded-For\", generateRandomIP())\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(\"Sec-Fetch-Dest\", \"empty\")\n\treq.Header.Set(\"Sec-Fetch-Mode\", \"cors\")\n\treq.Header.Set(\"Sec-Fetch-Site\", \"same-origin\")\n\t\n\tvar resp *http.Response\n\tvar responseBody []byte\n\t\n\t// 重试逻辑\n\tfor i := 0; i <= p.retries; i++ {\n\t\t// 发送请求\n\t\tresp, err = client.Do(req)\n\t\tif err != nil {\n\t\t\tif i == p.retries {\n\t\t\t\treturn nil, false, fmt.Errorf(\"请求失败: %w\", err)\n\t\t\t}\n\t\t\ttime.Sleep(500 * time.Millisecond)\n\t\t\tcontinue\n\t\t}\n\t\t\n\t\tdefer resp.Body.Close()\n\t\t\n\t\t// 读取响应体\n\t\tresponseBody, err = io.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\tif i == p.retries {\n\t\t\t\treturn nil, false, fmt.Errorf(\"读取响应失败: %w\", err)\n\t\t\t}\n\t\t\ttime.Sleep(500 * time.Millisecond)\n\t\t\tcontinue\n\t\t}\n\t\t\n\t\t// 状态码检查","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/pan666/pan666.go#L189-L225","documentation":"pan666's fetchPage returns this when client.Do(req) fails on the final retry attempt (i == p.retries). Earlier failures sleep 500ms and retry; once retries are exhausted the transport error (DNS, timeout, connection refused, TLS) is wrapped and returned. The req object is reused across attempts.","triggerScenarios":"client.Do returns err on every attempt of the retry loop: unreachable host, DNS failure, TLS handshake error, context deadline exceeded, or connection reset before any response.","commonSituations":"pan666 API domain blocked or DNS-poisoned in the region; no outbound network in the deployment environment; server drops requests with the spoofed X-Forwarded-For header; client timeout too short for a slow upstream.","solutions":["Inspect the wrapped transport error to identify DNS vs timeout vs TLS","curl the same URL from the host to confirm reachability","Increase the http.Client timeout if deadline exceeded","If the host blocks spoofed headers, stop sending the random X-Forwarded-For header"],"exampleFix":"// before\nresp, err = client.Do(req)\nif err != nil {\n    if i == p.retries { return nil, false, fmt.Errorf(\"请求失败: %w\", err) }\n// after\nresp, err = client.Do(req)\nif err != nil {\n    if i == p.retries { return nil, false, fmt.Errorf(\"请求失败 after %d tries: %w\", p.retries+1, err) }","handlingStrategy":"retry","validationCode":"func pan666Reachable() error {\n    c, err := net.DialTimeout(\"tcp\", \"pan666.example:443\", 3*time.Second)\n    if err != nil { return err }\n    c.Close()\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) && netErr.Timeout() {\n        client.Timeout = 30 * time.Second // retry with longer timeout\n    }\n    return err\n}","preventionTips":["Set a realistic client timeout for slow upstreams","Log the wrapped transport error type to distinguish DNS/TLS/timeout","Pre-check DNS resolution in constrained environments","Avoid spoofed headers that some hosts reject outright"],"tags":["network","http","retry","plugin"],"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"}