{"record":{"id":"fca96abd43657b29","repo":"fish2018/pansou","slug":"page-d-search-failed-w","errorCode":null,"errorMessage":"page %d search failed: %w","messagePattern":"page (.+?) search failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/melost/melost.go","lineNumber":88,"sourceCode":"}\n\n// doSearch 实际搜索实现\nfunc (p *MelostAsyncPlugin) doSearch(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {\n\tdebugLog(\"开始搜索，关键词: %s\", keyword)\n\n\tresultChan := make(chan []MelostItem, DefaultMaxPages)\n\terrChan := make(chan error, DefaultMaxPages)\n\n\tvar wg sync.WaitGroup\n\tfor page := 1; page <= DefaultMaxPages; page++ {\n\t\twg.Add(1)\n\n\t\tgo func(pageNum int) {\n\t\t\tdefer wg.Done()\n\n\t\t\titems, err := p.searchPage(client, keyword, pageNum)\n\t\t\tif err != nil {\n\t\t\t\terrChan <- fmt.Errorf(\"page %d search failed: %w\", pageNum, err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tresultChan <- items\n\t\t}(page)\n\t}\n\n\tgo func() {\n\t\twg.Wait()\n\t\tclose(resultChan)\n\t\tclose(errChan)\n\t}()\n\n\tvar allItems []MelostItem\n\tfor items := range resultChan {\n\t\tallItems = append(allItems, items...)\n\t}\n","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/melost/melost.go#L70-L106","documentation":"Melost plugin's doSearch fans out one goroutine per page calling p.searchPage; any error from a page is wrapped as \"page %d search failed: %w\" and sent to errChan. If all pages fail (len(allItems)==0), the first such error is returned, so this wrapper typically carries an underlying cause like a network failure, non-200 status, or API error from searchPage.","triggerScenarios":"Any of the DefaultMaxPages concurrent searchPage goroutines fails — e.g. the melost.cn API returns a non-200 status, times out, or returns apiResp.Code != 200 for that page; this wrapper adds the page number.","commonSituations":"melost.cn is down or rate-limiting concurrent requests (all goroutines fire simultaneously), timeout under DefaultTimeout due to slow upstream, or the search API changed its endpoint/contract.","solutions":["Read the wrapped cause (%w) to see which of searchPage's errors fired (request failed / unexpected status code / api returned error)","Note errors are only surfaced when ALL pages return zero items; if some pages succeed the search still returns partial results — check debug logs '收集到 N 条原始结果，M 个错误'","If rate-limited (concurrent requests), serialize or throttle the per-page goroutines","Verify melost.cn API availability and that MelostSearchAPI is still the correct endpoint"],"exampleFix":"// before: all errors dropped except errors[0]\nif len(allItems) == 0 && len(errors) > 0 {\n\treturn nil, errors[0]\n}\n// after: join all page errors for full context\nif len(allItems) == 0 && len(errors) > 0 {\n\treturn nil, errors.Join(errors...)\n}","handlingStrategy":"try-catch","validationCode":"// check upstream health before fanning out\nif _, err := client.Get(\"https://www.melost.cn\"); err != nil {\n\treturn nil, fmt.Errorf(\"melost unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"results, err := p.doSearch(client, keyword, ext)\nif err != nil {\n\tvar pageErr error\n\tif errors.As(err, &pageErr) && strings.Contains(pageErr.Error(), \"page \") {\n\t\tlog.Printf(\"melost page failure: %v\", pageErr)\n\t}\n\treturn nil, err\n}","preventionTips":["Check the underlying wrapped error before blaming the fan-out logic","Throttle per-page goroutines to avoid tripping server rate limits","Treat partial success (some pages OK) as acceptable; log skipped pages","Keep debug logging enabled to correlate item/error counts per search"],"tags":["network","concurrency","scraping","error-wrapping"],"backgroundTag":"api-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"}