{"record":{"id":"c4811af908b2176b","repo":"fish2018/pansou","slug":"detail-status-d","errorCode":null,"errorMessage":"detail status=%d","messagePattern":"detail status=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"plugin/panzun/panzun.go","lineNumber":281,"sourceCode":"\tfor _, item := range ordered {\n\t\tif item.ok {\n\t\t\tresults = append(results, item.result)\n\t\t}\n\t}\n\n\treturn results, nil\n}\n\nfunc (p *PanzunPlugin) fetchDiscussionLinks(client *http.Client, discussionID string) ([]model.Link, string, []string, time.Time, error) {\n\tdetailURL := fmt.Sprintf(\"%s/discussions/%s\", apiBase, discussionID)\n\tresp, err := p.scraper.Get(detailURL)\n\tif err != nil {\n\t\treturn nil, \"\", nil, time.Time{}, err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, \"\", nil, time.Time{}, fmt.Errorf(\"detail status=%d\", resp.StatusCode)\n\t}\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, \"\", nil, time.Time{}, err\n\t}\n\n\tvar detailResp struct {\n\t\tData     Discussion         `json:\"data\"`\n\t\tIncluded []IncludedResource `json:\"included\"`\n\t}\n\tif err := jsonutil.Unmarshal(body, &detailResp); err != nil {\n\t\treturn nil, \"\", nil, time.Time{}, err\n\t}\n\n\tincludedMap := buildIncludedMap(detailResp.Included)\n\trel := detailResp.Data.Relationships\n","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panzun/panzun.go#L263-L299","documentation":"fetchDiscussionLinks fetches a single discussion detail page via p.scraper.Get and returns this compact error when the HTTP status is not 200. The caller (detail worker goroutine) logs a warning and skips that discussion's links rather than failing the whole search.","triggerScenarios":"GET of /api/discussions/{id} returns 403 (Cloudflare block), 404 (discussion deleted), or 429/5xx while resolving download links for one search result.","commonSituations":"Individual discussion removed since indexing; per-IP rate limiting on detail requests; Cloudflare challenge triggered by bursts of detail fetches (4 concurrent workers).","solutions":["Check the status code in the error — 404 means the discussion is gone and should be skipped","Slow down detail requests or lower detailWorkers to avoid 429","Pass Cloudflare challenges via cloudscraper updates or proxies for 403/503","Treat it as non-fatal: the search already degrades gracefully by dropping that result"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"detail status=404\") {\n        // discussion deleted: drop result silently\n    } else if strings.Contains(err.Error(), \"detail status=429\") {\n        // rate limited: back off detail workers\n    }\n}","preventionTips":["Keep detailWorkers low to avoid tripping rate limits","Treat per-item detail failures as non-fatal (the plugin already does)","Rotate proxies/cookies when 403s cluster"],"tags":["go","http","scraping","status-code","detail-page"],"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"}