{"record":{"id":"9be97f2ca8e997e2","repo":"fish2018/pansou","slug":"s-d-9be97f","errorCode":null,"errorMessage":"[%s] 搜索返回状态码: %d","messagePattern":"\\[(.+?)\\] 搜索返回状态码: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/mikuclub/mikuclub.go","lineNumber":253,"sourceCode":"\treqURL := fmt.Sprintf(\"https://www.mikuclub.uk/wp-json/utils/v2/post_list?%s\", params.Encode())\n\n\tctx, cancel := context.WithTimeout(context.Background(), searchTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建搜索请求失败: %w\", p.Name(), err)\n\t}\n\tsetCommonHeaders(req, \"https://www.mikuclub.uk/\")\n\n\tresp, err := p.doRequestWithRetry(req, client, searchMaxRetries)\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\tvar payload postListResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析搜索结果失败: %w\", p.Name(), err)\n\t}\n\n\treturn payload.Posts, nil\n}\n\nfunc (p *MikuclubPlugin) fetchDetailLinks(client *http.Client, postID int64, detailURL string) []model.Link {\n\tif cached, ok := detailCache.Load(postID); ok {\n\t\tif entry, valid := cached.(cacheEntry); valid {\n\t\t\tif time.Now().Before(entry.expiresAt) && len(entry.links) > 0 {\n\t\t\t\treturn entry.links\n\t\t\t}\n\t\t\tdetailCache.Delete(postID)\n\t\t}","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/mikuclub/mikuclub.go#L235-L271","documentation":"This error is returned by MikuclubPlugin.fetchCategoryPosts when the WordPress search API (https://www.mikuclub.uk/wp-json/utils/v2/post_list) responds with a status code other than 200. The plugin aborts the category search instead of trying to decode a body that is not a valid postListResponse. The numeric code is embedded in the message so the caller can distinguish 403/429/5xx etc.","triggerScenarios":"fetchCategoryPosts calls doRequestWithRetry and the final HTTP response has StatusCode != http.StatusOK, e.g. the site returns 403 (bot protection / Anubis-like gate), 429 (rate limited), 500 (server error), or 404 after retries exhausted.","commonSituations":"The mikuclub.uk upstream site is down or under maintenance; anti-scraping protection blocks the plugin's default headers; too-aggressive keyword searching triggers rate limiting; network middleboxes/proxies inject 502/503 responses.","solutions":["Inspect the numeric status in the message; for 403/429 wait or reduce request rate, for 5xx retry later","Check https://www.mikuclub.uk directly in a browser to confirm the API is up","Update setCommonHeaders (User-Agent/Referer) to match a real browser if protection was added","Re-run the search; the plugin already retries via doRequestWithRetry with exponential backoff"],"exampleFix":"// before (caller sees raw error)\nresults, err := plugin.Search(\"keyword\", nil)\n// after (caller classifies status)\nresults, err := plugin.Search(\"keyword\", nil)\nif err != nil {\n    if strings.Contains(err.Error(), \"状态码: 429\") {\n        time.Sleep(time.Minute) // back off on rate limit\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// Go: check upstream health before searching\nresp, err := http.Head(\"https://www.mikuclub.uk/\")\nif err != nil || resp.StatusCode != http.StatusOK {\n    // skip search, site is down or blocking\n}","typeGuard":"func isUpstreamStatusError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"搜索返回状态码\")\n}","tryCatchPattern":"results, err := plugin.Search(keyword, nil)\nif err != nil {\n    if isUpstreamStatusError(err) {\n        log.Printf(\"mikuclub unavailable: %v\", err)\n        return fallbackResults, nil\n    }\n    return nil, err\n}","preventionTips":["Rate-limit searches to avoid 429s","Monitor upstream site availability before batch runs","Keep browser-like User-Agent/Referer headers current","Treat 5xx as transient and schedule retries"],"tags":["http","upstream","status-code","network"],"backgroundTag":"http-error-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"}