{"record":{"id":"5e3cbc164ada8f26","repo":"fish2018/pansou","slug":"susu-s-5e3cbc","errorCode":null,"errorMessage":"[susu] 帖子 %s 的下载按钮均未返回有效链接","messagePattern":"\\[susu\\] 帖子 (.+?) 的下载按钮均未返回有效链接","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/susu/susu.go","lineNumber":418,"sourceCode":"\t// 等待所有goroutine完成\n\tgo func() {\n\t\twgLinks.Wait()\n\t\tclose(linkChan)\n\t}()\n\n\t// 收集结果\n\tlinks := make([]model.Link, 0, totalButtons)\n\tseen := make(map[string]struct{}, totalButtons)\n\tfor link := range linkChan {\n\t\tkey := link.Type + \"\\x00\" + link.URL + \"\\x00\" + link.Password\n\t\tif _, exists := seen[key]; exists {\n\t\t\tcontinue\n\t\t}\n\t\tseen[key] = struct{}{}\n\t\tlinks = append(links, link)\n\t}\n\tif len(links) == 0 {\n\t\treturn nil, fmt.Errorf(\"[susu] 帖子 %s 的下载按钮均未返回有效链接\", postID)\n\t}\n\n\t// 缓存结果\n\tbuttonListCache.Store(postID, links)\n\n\treturn links, nil\n}\n\n// getButtonDetail 获取按钮详情\nfunc (p *SusuAsyncPlugin) getButtonDetail(client *http.Client, postID string, index, i int) (model.Link, error) {\n\t// 生成缓存键\n\tcacheKey := fmt.Sprintf(\"%s:%d:%d\", postID, index, i)\n\n\t// 检查缓存\n\tif cachedLink, ok := buttonDetailCache.Load(cacheKey); ok {\n\t\treturn cachedLink.(model.Link), nil\n\t}\n","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/susu/susu.go#L400-L436","documentation":"getLinks throws this when the post had download buttons (totalButtons > 0) but every button's link-resolution attempt either failed or produced duplicates filtered out by the seen-dedup, leaving zero valid links. All per-button fetches errored, timed out, or returned unusable URLs (e.g. all empty/dead).","triggerScenarios":"After consuming linkChan and deduplicating via seen[key], len(links) == 0 — every download button's resolver failed (network errors, per-button timeouts, HTTP errors) or every candidate link was filtered as invalid/duplicate.","commonSituations":"The download host(s) being down or geo-blocked while the button-list API still works; expired/dead file links on an old post; per-button resolvers broken after a site layout change; MaxConcurrency/semaphore starving under timeouts.","solutions":["Check the per-button error paths' logs to see whether failures are network, HTTP status, or parse errors.","Verify the download hosts directly (open one button's URL in a browser) — links may simply be dead.","Confirm the per-button HTML/JSON extraction still matches the current site markup.","Retry later if the download host is temporarily down; consider increasing retries/timeouts for individual link fetches.","If all links dedupe to nothing, inspect the key used in seen — an over-aggressive dedup key could filter valid links."],"exampleFix":"null","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"links, err := p.getLinks(postID)\nif err != nil && strings.Contains(err.Error(), \"均未返回有效链接\") {\n    // per-button resolvers all failed; try alternate source or report dead links\n    return alternateResolver.Resolve(postID)\n}","preventionTips":["Monitor the download hosts independently of the button-list API","Log per-button failures to distinguish dead links from extraction bugs","Keep per-button HTML extraction updated with site changes","Provide a secondary resolver or cached links as fallback","Review the dedup key so valid links aren't filtered as duplicates"],"tags":["empty-result","link-resolution","downstream-failure","scraping"],"backgroundTag":"empty-result-set","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"}