fish2018/pansou · error

[susu] 获取按钮列表失败

Error message

[susu] 获取按钮列表失败: %w

What it means

getLinks wraps errors from doRequestWithRetry when fetching the button-list API endpoint. Like [700], the retried POST to ButtonListURL never produced a response: connection failures, timeouts, or retries exhausted over MaxRetries attempts. The 20-second context timeout also surfaces as this error when exceeded.

Solutions

  1. Unwrap the error chain to see the root cause (deadline exceeded vs connection refused).
  2. Raise the 20s context timeout if the API is legitimately slow.
  3. Confirm the API host is reachable (curl -X POST ButtonListURL with the same form) from the host.
  4. Check MaxRetries/backoff settings; increase them for flaky networks.
  5. If the endpoint moved, update ButtonListURL.

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

conn, err := net.DialTimeout("tcp", apiHost+":443", 5*time.Second)
if err != nil { /* API host unreachable, skip link resolution */ }
conn.Close()

Try / catch

links, err := p.getLinks(postID)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        // increase timeout or retry with backoff
    }
    log.Printf("button-list fetch failed: %v", err)
    return nil, err
}

Prevention

When it happens

Trigger: Calling getLinks (via the resolver chain from an anonymous goroutine/caller) when the POST to ButtonListURL fails at transport level: ctx deadline exceeded after 20s, connection refused, TLS failure, or MaxRetries exhausted.

Common situations: The API endpoint being slower than the 20s context timeout under load; the API host blocked or DNS-failing; the site rate-limiting repeated getLinks calls; container without outbound access to the API host.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/f5ab3df267158d40. Report an issue: GitHub.

Appendix: source

Thrown at plugin/susu/susu.go:355

		return cachedLinks.([]model.Link), nil
	}

	form := url.Values{
		"post_id": {postID},
		"guest":   {""},
	}
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, ButtonListURL, strings.NewReader(form.Encode()))
	if err != nil {
		return nil, fmt.Errorf("[susu] 创建按钮列表请求失败: %w", err)
	}
	setAPIHeaders(req, fmt.Sprintf("%s/%s.html", BaseURL, postID))

	resp, err := p.doRequestWithRetry(client, req, MaxRetries)
	if err != nil {
		return nil, fmt.Errorf("[susu] 获取按钮列表失败: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		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 {

View on GitHub (pinned to beaa561337)