{"record":{"id":"e0fc507cde9a3ca1","repo":"fish2018/pansou","slug":"s-d-e0fc50","errorCode":null,"errorMessage":"[%s] 详情页返回状态码: %d","messagePattern":"\\[(.+?)\\] 详情页返回状态码: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/mizixing/mizixing.go","lineNumber":254,"sourceCode":"\nfunc (p *MizixingPlugin) fetchDetailData(client *http.Client, detailURL string) (detailData, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), detailTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, detailURL, nil)\n\tif err != nil {\n\t\treturn detailData{}, fmt.Errorf(\"[%s] 创建详情页请求失败: %w\", p.Name(), err)\n\t}\n\tsetHTMLHeaders(req, detailURL)\n\n\tresp, err := p.doRequestWithRetry(req, client, maxRequestRetries)\n\tif err != nil {\n\t\treturn detailData{}, err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn detailData{}, fmt.Errorf(\"[%s] 详情页返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn detailData{}, fmt.Errorf(\"[%s] 解析详情页失败: %w\", p.Name(), err)\n\t}\n\n\tcontent := doc.Find(\"article.article-content\")\n\tif content.Length() == 0 {\n\t\tcontent = doc.Find(\".article-content\")\n\t}\n\tif content.Length() == 0 {\n\t\tcontent = doc.Find(\".entry-content\")\n\t}\n\tif content.Length() == 0 {\n\t\tcontent = doc.Selection\n\t}\n","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/mizixing/mizixing.go#L236-L272","documentation":"This error is raised by fetchDetailData in the Mizixing plugin when the detail page HTTP response does not return status 200. The plugin aborts parsing because the body likely does not contain the expected HTML article structure. It wraps the plugin name and the actual status code so the caller knows which upstream response failed.","triggerScenarios":"Triggered whenever an HTTP GET to the Mizixing detail page completes but resp.StatusCode != http.StatusOK (e.g. 403 from anti-bot protection, 404 for a stale detail URL, 429 rate limiting, 5xx server errors).","commonSituations":"Site temporarily down or under maintenance; IP blocked by WAF/CDN; the detail URL was constructed from an outdated or invalid item ID; heavy scraping triggering rate limits.","solutions":["Log the status code and check the target site availability in a browser or with curl to identify whether it's 4xx (URL/blocking) or 5xx (server side)","Ensure a realistic User-Agent/browser-like header set is sent to avoid 403 anti-bot responses","Add or increase retry with backoff for transient 5xx/429 responses before failing","Verify the detail URL is built from a valid, current item ID returned by search","Handle non-200 gracefully upstream (skip the item) instead of crashing the whole search run"],"exampleFix":"// before\nresp, err := p.doRequest(req)\nif resp.StatusCode != http.StatusOK {\n    return detailData{}, fmt.Errorf(\"[%s] 详情页返回状态码: %d\", p.Name(), resp.StatusCode)\n}\n// after\nresp, err := p.doRequest(req)\nif err != nil {\n    return detailData{}, err\n}\nif resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {\n    if r, rerr := p.doRequestWithRetry(req); rerr == nil {\n        resp = r\n    }\n}\nif resp.StatusCode != http.StatusOK {\n    return detailData{}, fmt.Errorf(\"[%s] 详情页返回状态码: %d\", p.Name(), resp.StatusCode)\n}","handlingStrategy":"retry","validationCode":"// pre-check before calling search\ndetailURL := buildDetailURL(id)\nif u, err := url.Parse(detailURL); err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid detail url: %s\", detailURL)\n}","typeGuard":null,"tryCatchPattern":"detail, err := p.fetchDetailData(id)\nif err != nil {\n    var httpErr interface{ Unwrap() error }\n    log.Printf(\"detail fetch failed, skipping item: %v\", err)\n    return fallbackResult(id) // degrade gracefully\n}","preventionTips":["Send full browser-like headers to avoid 403 anti-bot responses","Retry transient statuses (429, 5xx) with exponential backoff","Validate detail URLs before requesting","Check target site health before bulk scraping runs"],"tags":["http","network","scraping","go"],"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"}