fish2018/pansou · error

下载链接JSON解析失败

Error message

下载链接JSON解析失败: %w

What it means

getDownloadLinks fails to json.Unmarshal the response body into []CygDownload and wraps the error with "下载链接JSON解析失败". It means the server replied 200 but the body is not the expected JSON array of download objects.

Solutions

  1. Dump the raw body (on unmarshal failure) to see what was actually returned.
  2. Compare the response against the CygDownload struct and update its json field tags after a site schema change.
  3. Check whether the endpoint now returns an object wrapper instead of a bare array and adjust the target type.
  4. Verify Content-Type is application/json; if HTML, treat it as an anti-bot/upstream error rather than a parse bug.

Example fix

// before
var downloadData []CygDownload
if err := json.Unmarshal(body, &downloadData); err != nil {
    return nil, fmt.Errorf("下载链接JSON解析失败: %w", err)
}
// after
var downloadData []CygDownload
if err := json.Unmarshal(body, &downloadData); err != nil {
    return nil, fmt.Errorf("下载链接JSON解析失败: %w, body: %.200s", err, body)
}
Defensive patterns

Strategy: validation

Validate before calling

ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "json") {
    return fmt.Errorf("expected JSON, got %s", ct)
}

Try / catch

links, err := p.getDownloadLinks(id)
if err != nil && strings.Contains(err.Error(), "JSON解析失败") {
    // response was not the expected schema; treat source as changed/broken
    return nil, fmt.Errorf("source schema changed, plugin update needed: %w", err)
}

Prevention

When it happens

Trigger: The 200 response body is HTML (error page / anti-bot challenge), empty, or its JSON schema changed so it no longer unmarshals into []CygDownload.

Common situations: Site deployed a new version changing the download API response shape, WAF serving an HTML challenge with status 200, empty body due to upstream cache miss, or CDN returning a compressed body the client did not request.

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/b448a4db2b569b1a. Report an issue: GitHub.

Appendix: source

Thrown at plugin/cyg/cyg.go:257

	if err != nil {
		return nil, fmt.Errorf("下载链接请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查状态码
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("下载链接请求状态码: %d", resp.StatusCode)
	}

	// 解析响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取下载链接响应失败: %w", err)
	}

	var downloadData []CygDownload
	if err := json.Unmarshal(body, &downloadData); err != nil {
		return nil, fmt.Errorf("下载链接JSON解析失败: %w", err)
	}

	// 转换为model.Link格式
	return p.convertToLinks(downloadData), nil
}

// convertToSearchResult 转换为标准搜索结果格式
func (p *CygPlugin) convertToSearchResult(post CygPost, links []model.Link) model.SearchResult {
	return model.SearchResult{
		UniqueID: fmt.Sprintf("cyg-%d", post.ID),
		Title:    p.cleanHTML(post.Title.Rendered),
		Content:  p.cleanHTML(post.Excerpt.Rendered),
		Datetime: p.parseDateTime(post.Date),
		Tags:     []string{post.CategoryName},
		Links:    links,
		Channel:  "", // 插件搜索结果必须为空字符串
	}
}

View on GitHub (pinned to beaa561337)