{"record":{"id":"8385d58d505fe49e","repo":"fish2018/pansou","slug":"s-w-8385d5","errorCode":null,"errorMessage":"[%s] 请求失败: %w","messagePattern":"\\[(.+?)\\] 请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/jupansou/jupansou.go","lineNumber":117,"sourceCode":"\t}\n\tctx, cancel := context.WithTimeout(context.Background(), jupansouStreamTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建请求失败: %w\", p.Name(), err)\n\t}\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/event-stream\")\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\", jupansouBaseURL+\"/\")\n\treq.Header.Set(\"Origin\", jupansouBaseURL)\n\treq.Header.Set(\"X-Requested-With\", \"XMLHttpRequest\")\n\n\tresp, err := doJuPansouRequestWithRetry(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\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"[%s] 接口返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\n\titems := make([]juPansouStreamItem, 0)\n\tscanner := bufio.NewScanner(resp.Body)\n\tscanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)\n\tfor scanner.Scan() {\n\t\tline := strings.TrimSpace(scanner.Text())\n\t\tif !strings.HasPrefix(line, \"data:\") {\n\t\t\tcontinue\n\t\t}\n\n\t\tpayload := strings.TrimSpace(strings.TrimPrefix(line, \"data:\"))\n\t\tif payload == \"\" || payload == \"[DONE]\" {","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/jupansou/jupansou.go#L99-L135","documentation":"searchImpl wraps errors from doJuPansouRequestWithRetry, which performs the actual HTTP call with retries. It fires when the request cannot be delivered at all (connection refused, DNS failure, TLS error, context timeout) after all retry attempts. The underlying cause is preserved via %w.","triggerScenarios":"client.Do inside doJuPansouRequestWithRetry fails on every attempt: unreachable host, refused connection, TLS handshake failure, or the jupansouStreamTimeout context expiring.","commonSituations":"JuPansou API is down or its domain changed; corporate firewall/DNS blocks the host; the streaming endpoint is slower than the configured timeout; missing outbound internet in containers.","solutions":["Unwrap the error to see the root cause (timeout vs connection refused vs TLS).","Verify the upstream domain is still alive with curl from the host running the plugin.","Increase jupansouStreamTimeout if the SSE endpoint is slow to respond.","Configure a proxy if the host is unreachable from your network.","Check for rate limiting/IP bans — slow down request frequency or rotate IPs."],"exampleFix":"// before: opaque failure\nresults, err := p.searchImpl(client, keyword)\n// after: diagnose the cause\nif err != nil {\n    var nerr net.Error\n    if errors.As(err, &nerr) && nerr.Timeout() {\n        log.Println(\"jupansou timed out; consider raising jupansouStreamTimeout\")\n    }\n}","handlingStrategy":"try-catch","validationCode":"u, _ := url.Parse(jupansouBaseURL)\nconn, err := net.DialTimeout(\"tcp\", u.Host, 3*time.Second)\nif err != nil { return fmt.Errorf(\"jupansou host unreachable: %w\", err) }\nconn.Close()","typeGuard":null,"tryCatchPattern":"results, err := p.searchImpl(client, keyword)\nvar nerr net.Error\nif err != nil && errors.As(err, &nerr) {\n    if nerr.Timeout() {\n        log.Println(\"jupansou request timed out; raising timeout or retrying\")\n    } else {\n        log.Printf(\"jupansou transport error: %v\", nerr)\n    }\n    return fallbackResults\n}","preventionTips":["Set request timeouts generously for streaming endpoints and test from production-like networks.","Monitor upstream availability and disable the plugin gracefully when it is down.","Cache prior results to serve during outages."],"tags":["network","http","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"}