fish2018/pansou · error

解析响应失败

Error message

解析响应失败: %w

What it means

pan666 plugin fetchPage wraps json.Unmarshal failures of the search API response body with this Chinese message ('failed to parse response'). It means the upstream pan666 API returned a body that is not valid JSON (or not the expected Pan666Response shape). The plugin treats any non-decodable body as a hard failure and aborts the search.

Solutions

  1. Print/log the raw responseBody on failure to see what the upstream actually returned (HTML vs JSON).
  2. Verify the pan666 API endpoint is reachable in a browser or via curl; update the base URL if the site moved.
  3. Add browser-like headers (User-Agent, Referer, Cookie) to the request to bypass anti-bot pages.
  4. If the schema changed, update the Pan666Response struct fields to match the new JSON.

Example fix

// before
if err := json.Unmarshal(responseBody, &apiResp); err != nil {
    return nil, false, fmt.Errorf("解析响应失败: %w", err)
}
// after
if err := json.Unmarshal(responseBody, &apiResp); err != nil {
    return nil, false, fmt.Errorf("解析响应失败: %w (body: %.200s)", err, responseBody)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check before trusting the API
if len(responseBody) == 0 || responseBody[0] != '{' {
    return nil, false, fmt.Errorf("non-JSON response: %.200s", responseBody)
}

Type guard

func looksLikeJSON(b []byte) bool {
    t := bytes.TrimSpace(b)
    return len(t) > 0 && (t[0] == '{' || t[0] == '[')
}

Try / catch

results, partial, err := plugin.FetchPage(keyword)
if err != nil {
    var uerr *fmt.Errorf // or errors.As on wrapped json.UnmarshalTypeError
    log.Printf("pan666 parse failed: %v", err)
    return fallbackSearch(keyword)
}

Prevention

When it happens

Trigger: fetchPage receives an HTTP response whose body cannot be unmarshaled into Pan666Response: HTML error pages, Cloudflare/CAPTCHA interstitials, rate-limit text, empty bodies, or a changed upstream JSON schema.

Common situations: Upstream pan666 site is down or behind anti-bot protection; the plugin's User-Agent is blocked; the API endpoint changed its response format after a site update; a proxy/gateway returned a non-JSON error page.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at plugin/pan666/pan666.go:241

		}
		
		// 状态码检查
		if resp.StatusCode != http.StatusOK {
			if i == p.retries {
				return nil, false, fmt.Errorf("API返回非200状态码: %d", resp.StatusCode)
			}
			time.Sleep(500 * time.Millisecond)
			continue
		}
		
		// 请求成功,跳出重试循环
		break
	}
	
	// 解析响应
	var apiResp Pan666Response
	if err := json.Unmarshal(responseBody, &apiResp); err != nil {
		return nil, false, fmt.Errorf("解析响应失败: %w", err)
	}
	
	// 处理结果
	results := make([]model.SearchResult, 0, len(apiResp.Data))
	postMap := make(map[string]Pan666Post)
	
	// 创建帖子ID到帖子内容的映射
	for _, post := range apiResp.Included {
		postMap[post.ID] = post
	}
	
	// 遍历搜索结果
	for _, discussion := range apiResp.Data {
		// 获取相关帖子
		postID := discussion.Relationships.MostRelevantPost.Data.ID
		post, ok := postMap[postID]
		if !ok {
			continue

View on GitHub (pinned to beaa561337)