{"record":{"id":"04739c8a3a63c5b2","repo":"fish2018/pansou","slug":"susu-d","errorCode":null,"errorMessage":"[susu] 搜索请求返回状态码: %d","messagePattern":"\\[susu\\] 搜索请求返回状态码: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/susu/susu.go","lineNumber":165,"sourceCode":"\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"创建请求失败: %w\", err)\n\t}\n\n\t// 设置请求头\n\treq.Header.Set(\"User-Agent\", getRandomUA())\n\tsetBrowserHeaders(req, BaseURL+\"/\")\n\n\t// 发送请求（带重试）\n\tresp, err := p.doRequestWithRetry(client, req, MaxRetries)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"请求失败: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"[susu] 搜索请求返回状态码: %d\", resp.StatusCode)\n\t}\n\n\t// 解析HTML\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"解析HTML失败: %w\", err)\n\t}\n\n\t// 提取搜索结果\n\tvar wg sync.WaitGroup\n\tresultChan := make(chan model.SearchResult, 20)\n\n\t// 创建信号量控制并发数\n\tsemaphore := make(chan struct{}, MaxConcurrency)\n\n\t// 预先收集所有需要处理的项\n\tvar items []*goquery.Selection\n","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/susu/susu.go#L147-L183","documentation":"doSearch throws this when the retried search request succeeded at the transport level but the server answered with a status code other than 200 OK. The plugin treats any non-200 as a failed search and surfaces the raw status code so the caller can distinguish 403 (bot blocking), 404, 429 (rate limit), 5xx, etc. The response body is discarded without parsing.","triggerScenarios":"doSearch receives resp.StatusCode != http.StatusOK after doRequestWithRetry returns a response — e.g. Cloudflare/WAF challenge page (403), rate limiting (429), maintenance (503), or a redirect to an error page.","commonSituations":"The site's anti-bot protection flagging the request (missing/expired cookies or UA); too-frequent searches from one IP; the site being partially down; Cloudflare returning 5xx during outages.","solutions":["Log/check the numeric status in the message: 403/503 often mean bot protection — verify setBrowserHeaders/getRandomUA produce plausible browser headers.","If 429, back off and reduce search frequency or add rate limiting between calls.","If 5xx, retry later; the site is having issues.","Confirm BaseURL is current — a stale domain can return unexpected codes (e.g. parking pages).","Consider extending doRequestWithRetry to also retry on 5xx/429 responses, not only transport errors."],"exampleFix":"null","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"links, err := p.Search(query)\nif err != nil {\n    var statusErr interface{ Error() string }\n    if strings.Contains(err.Error(), \"状态码: 403\") || strings.Contains(err.Error(), \"状态码: 429\") {\n        // honor backoff / rotate headers before retry\n    }\n}","preventionTips":["Keep browser-like headers/UA fresh to avoid WAF blocks","Rate-limit searches to avoid 429s","Alert on sustained non-200 responses (site outage or endpoint drift)","Retry only on 5xx/429, fail fast on 4xx"],"tags":["http-status","non-200","search","anti-bot"],"backgroundTag":"http-non-200-response","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"}