fish2018/pansou · warning
[susu] 帖子 没有可用下载按钮
Error message
[susu] 帖子 %s 没有可用下载按钮
What it means
getLinks throws this when the button-list JSON decoded successfully but the total count of buttons across all groups is zero — the post exists (or the API pretends it does) yet exposes no download buttons. This is a domain-level empty-result guard, typically meaning the postID is wrong, the post was deleted, or it never had download content.
Solutions
- Verify the postID by opening BaseURL/<postID>.html in a browser and confirming download buttons render.
- Check that the JSON groups actually map to the current site structure (a field rename can silently zero out Button).
- Handle gracefully upstream: treat as 'no downloadable content' rather than a hard failure when appropriate.
- Refresh cached search results — the post may have been deleted since the search index cached it.
Example fix
null
Defensive patterns
Strategy: fallback
Validate before calling
// resolve links only for postIDs known to have content
if postID == "" || !postIDPattern.MatchString(postID) {
// skip getLinks for malformed IDs
} Try / catch
links, err := p.getLinks(postID)
if err != nil && strings.Contains(err.Error(), "没有可用下载按钮") {
// treat as 'no downloadable content', not a hard error
return model.LinkResults{}, nil
} Prevention
- Validate postIDs come from a fresh search, not stale caches
- Confirm posts still exist before resolving links
- Expect legitimately empty posts and handle them gracefully
- Check the downloadGroup struct maps the API fields (a rename can zero out Button)
When it happens
Trigger: After json.Unmarshal into []downloadGroup, summing len(group.Button) over all groups yields 0 — empty array, groups with empty Button slices, or a structurally valid but contentless response (e.g. API returning [] for unknown postIDs).
Common situations: Passing a stale or mistyped postID; the post's downloads were removed or the post deleted; scraping a post type that uses a different download mechanism; API returning empty results for region/language variants.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/4d8c6f3579a0288b.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/susu/susu.go:377
return nil, fmt.Errorf("[susu] 按钮列表请求返回状态码: %d", resp.StatusCode)
}
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 2<<20))
if err != nil {
return nil, fmt.Errorf("[susu] 读取按钮列表失败: %w", err)
}
var groups []downloadGroup
if err := json.Unmarshal(respBody, &groups); err != nil {
return nil, fmt.Errorf("[susu] 解析按钮列表失败: %w", err)
}
totalButtons := 0
for _, group := range groups {
totalButtons += len(group.Button)
}
if totalButtons == 0 {
return nil, fmt.Errorf("[susu] 帖子 %s 没有可用下载按钮", postID)
}
linkChan := make(chan model.Link, totalButtons)
var wgLinks sync.WaitGroup
semaphore := make(chan struct{}, MaxConcurrency)
for groupIndex, group := range groups {
for buttonIndex := range group.Button {
wgLinks.Add(1)
go func(index, i int) {
defer wgLinks.Done()
semaphore <- struct{}{}
defer func() { <-semaphore }()
link, err := p.getButtonDetail(client, postID, index, i)
if err == nil && link.URL != "" {
linkChan <- link
}View on GitHub (pinned to beaa561337)