{"record":{"id":"515d5097f7cad07c","repo":"fish2018/pansou","slug":"s-w-515d50","errorCode":null,"errorMessage":"[%s] 搜索请求失败: %w","messagePattern":"\\[(.+?)\\] 搜索请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/miosou/miosou.go","lineNumber":104,"sourceCode":"\tif keyword == \"\" {\n\t\treturn nil, nil\n\t}\n\tif err := p.ensureGate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor attempt := 0; attempt < 2; attempt++ {\n\t\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\t\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, apiBaseURL+\"/search?keyword=\"+url.QueryEscape(keyword), nil)\n\t\tif err != nil {\n\t\t\tcancel()\n\t\t\treturn nil, fmt.Errorf(\"[%s] 创建搜索请求失败: %w\", p.Name(), err)\n\t\t}\n\t\tsetHeaders(req, \"text/event-stream\")\n\t\tresp, err := p.client.Do(req)\n\t\tif err != nil {\n\t\t\tcancel()\n\t\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t\t}\n\t\tif isAnubisGateResponse(resp) {\n\t\t\tresp.Body.Close()\n\t\t\tcancel()\n\t\t\tp.invalidateGate()\n\t\t\tif err := p.ensureGate(); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif resp.StatusCode != http.StatusOK {\n\t\t\tresp.Body.Close()\n\t\t\tcancel()\n\t\t\treturn nil, fmt.Errorf(\"[%s] 搜索接口返回状态码: %d\", p.Name(), resp.StatusCode)\n\t\t}\n\t\tgroups, err := parseSearchStream(resp.Body)\n\t\tresp.Body.Close()\n\t\tif err != nil {","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/miosou/miosou.go#L86-L122","documentation":"This error is returned by MiosouPlugin.searchImpl when p.client.Do fails to execute the search HTTP request (transport-level failure). It wraps the underlying *url.Error, so timeouts, DNS failures, connection resets, and TLS errors all land here on either of the 2 attempts.","triggerScenarios":"searchImpl calls p.client.Do(req) and it returns a non-nil error: requestTimeout context expired, DNS resolution of the API host failed, TCP connect refused/reset, TLS handshake failure, or the client's Timeout fired first.","commonSituations":"The miosou API host is down or blocked from the user's network region; requestTimeout is too short for a slow link; a corporate proxy intercepts TLS; DNS misconfiguration on the host.","solutions":["Inspect the wrapped *url.Error to distinguish timeout vs connection refused vs TLS","Verify reachability: curl the apiBaseURL/search endpoint from the same host","Increase requestTimeout (both the client Timeout and per-attempt context) if timeouts dominate","Check DNS/proxy settings; if the host requires a proxy, configure http.Transport Proxy"],"exampleFix":"// before\nresp, err := p.client.Do(req)\nif err != nil {\n    return nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n}\n// after\ndecision, derr := dialContext(ctx, \"tcp\", \"proxy.local:8080\")\n_ = decision; _ = derr\nclient := &http.Client{Timeout: requestTimeout, Transport: &http.Transport{Proxy: http.ProxyFromEnvironment}}\nresp, err := client.Do(req)\nif err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) && netErr.Timeout() {\n        return nil, fmt.Errorf(\"[%s] 搜索超时(%v): %w\", p.Name(), requestTimeout, err)\n    }\n    return nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n}","handlingStrategy":"retry","validationCode":"// Go: pre-flight reachability check\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\nreq, _ := http.NewRequestWithContext(ctx, http.MethodHead, apiBaseURL, nil)\nif _, err := p.client.Do(req); err != nil {\n    // upstream unreachable: fail fast with clear message\n}","typeGuard":"func isTimeoutErr(err error) bool {\n    var netErr net.Error\n    return errors.As(err, &netErr) && netErr.Timeout()\n}","tryCatchPattern":"resp, err := p.client.Do(req)\nif err != nil {\n    var netErr net.Error\n    switch {\n    case errors.As(err, &netErr) && netErr.Timeout():\n        return nil, fmt.Errorf(\"search timed out after %v: %w\", requestTimeout, err)\n    default:\n        return nil, fmt.Errorf(\"search transport error: %w\", err)\n    }\n}","preventionTips":["Set http.Client Timeout and context timeouts consistently","Configure ProxyFromEnvironment if the host needs a proxy","Check DNS health on the deployment host","Distinguish timeouts from refusals in logs"],"tags":["network","http","timeout","dns"],"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"}