fish2018/pansou · warning

[ ] 搜索响应超过 字节

Error message

[%s] 搜索响应超过 %d 字节

What it means

Returned by searchImpl when the response body exceeds maxResponseSize (3 MiB, 3 << 20 bytes). The body is read through a LimitReader of maxResponseSize+1 bytes; if more than maxResponseSize bytes were actually read, the plugin rejects the response instead of processing an unexpectedly huge page. This is a defensive guard against the upstream site returning garbage, error pages with huge payloads, or being redirected to a different site.

Solutions

  1. Verify the effective final URL (resp.Request.URL) — a redirect to an unexpected domain indicates baseURL/domain takeover; update baseURL
  2. Check what the site actually returns with curl to confirm the page legitimately grew
  3. Raise maxResponseSize deliberately if the upstream page size grew
  4. Keep the guard but alert on it, since it usually signals a changed or hijacked upstream

Example fix

// before
body, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseSize+1))
// after
body, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseSize+1))
if len(body) > maxResponseSize {
    return nil, fmt.Errorf("[%s] 搜索响应超过 %d 字节 (final URL: %s)", p.Name(), maxResponseSize, resp.Request.URL)
}
Defensive patterns

Strategy: fallback

Validate before calling

// cannot be pre-validated; size only known after reading

Try / catch

if strings.Contains(err.Error(), "搜索响应超过") {
    // treat as upstream anomaly: log resp.Request.URL and skip this source,
    // don't crash the whole search
}

Prevention

When it happens

Trigger: len(body) > maxResponseSize after reading: the site returns an unusually large page, a redirect to unrelated content (parked domain, ad interstitial), or an HTML error page bloated with scripts.

Common situations: The haitunsou domain expires or is taken over and the plugin is silently redirected to an unrelated large page; upstream begins embedding much more data in pages; misconfigured baseURL points at a mirror returning huge pages.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


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

Appendix: source

Thrown at plugin/haitunsou/haitunsou.go:108

	if err != nil {
		return nil, fmt.Errorf("[%s] 创建搜索请求失败: %w", p.Name(), err)
	}
	setRequestHeaders(req, p.baseURL)

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("[%s] 搜索请求返回 HTTP %d", p.Name(), resp.StatusCode)
	}
	body, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseSize+1))
	if err != nil {
		return nil, fmt.Errorf("[%s] 读取搜索响应失败: %w", p.Name(), err)
	}
	if len(body) > maxResponseSize {
		return nil, fmt.Errorf("[%s] 搜索响应超过 %d 字节", p.Name(), maxResponseSize)
	}

	items, err := parseEmbeddedList(body)
	if err != nil {
		return nil, fmt.Errorf("[%s] 解析搜索结果失败: %w", p.Name(), err)
	}
	results := make([]model.SearchResult, 0, len(items))
	seen := make(map[string]struct{}, len(items))
	for _, item := range items {
		result, ok := convertItem(item)
		if !ok {
			continue
		}
		key := result.Links[0].URL + "\x00" + result.Links[0].Password
		if _, exists := seen[key]; exists {
			continue
		}
		seen[key] = struct{}{}

View on GitHub (pinned to beaa561337)