fish2018/pansou · error

响应缺少 merged_by_type

Error message

响应缺少 merged_by_type

What it means

The Seroval response parsed successfully, but navigating node.result -> searchResults -> merged_by_type (with reference resolution) yielded a nil node or a node without Props. The plugin requires merged_by_type to enumerate search results grouped by link type, so it returns this error when the expected structure is missing.

Solutions

  1. Verify the server function ID is current by re-running discovery; an invalid ID commonly yields an unexpected payload shape.
  2. Confirm with a browser DevTools capture what a real (non-empty) response looks like and compare node paths (result.searchResults.merged_by_type).
  3. Handle the empty-results case explicitly before erroring if zero hits legitimately omit merged_by_type.
  4. Update the decoder navigation keys if the field was renamed upstream.

Example fix

// before
if mergedNode == nil || mergedNode.Props == nil {
	return nil, fmt.Errorf("响应缺少 merged_by_type")
}
// after
if mergedNode == nil || mergedNode.Props == nil {
	return []model.SearchResult{}, nil // treat as zero results
}
Defensive patterns

Strategy: type-guard

Validate before calling

var probe map[string]stdjson.RawMessage
if stdjson.Unmarshal(body, &probe) == nil {
	if _, ok := probe["result"]; !ok {
		return fmt.Errorf("response lacks result envelope")
	}
}

Type guard

func hasMergedByType(root *serovalNode, d *serovalDecoder) bool {
	n := d.resolve(d.objectValue(d.objectValue(d.objectValue(root, "result"), "searchResults"), "merged_by_type"))
	return n != nil && n.Props != nil
}

Try / catch

results, err := parseSearchResponse(body)
if err != nil {
	if strings.Contains(err.Error(), "响应缺少 merged_by_type") {
		return []model.SearchResult{}, nil // treat as empty result set
	}
	return nil, err
}

Prevention

When it happens

Trigger: decoder.objectValue/resolve produce a nil merged_by_type node or one with nil Props: the API call succeeded (valid JSON) but returned no search data — zero results shape, an API-level error payload, or a schema change.

Common situations: The search keyword returned no results and the API omits merged_by_type; the server function ID is wrong so a different payload shape comes back; the site upgraded and renamed/renested result fields.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at plugin/xiaokupan/xiaokupan.go:274

	hashes := hashPattern.FindAll(assetBody[windowStart:routeIndex], -1)
	if len(hashes) == 0 {
		return "", fmt.Errorf("入口脚本未找到搜索接口标识")
	}
	return string(hashes[len(hashes)-1]), nil
}

func parseSearchResponse(body []byte) ([]model.SearchResult, error) {
	var root serovalNode
	if err := stdjson.Unmarshal(body, &root); err != nil {
		return nil, fmt.Errorf("解析 Seroval 响应失败: %w", err)
	}
	decoder := newSerovalDecoder(&root)
	resultNode := decoder.objectValue(&root, "result")
	searchResultsNode := decoder.objectValue(resultNode, "searchResults")
	mergedNode := decoder.objectValue(searchResultsNode, "merged_by_type")
	mergedNode = decoder.resolve(mergedNode)
	if mergedNode == nil || mergedNode.Props == nil {
		return nil, fmt.Errorf("响应缺少 merged_by_type")
	}

	results := make([]model.SearchResult, 0)
	seenURLs := make(map[string]struct{})
	for index, linkType := range mergedNode.Props.Keys {
		if index >= len(mergedNode.Props.Values) {
			break
		}
		arrayNode := decoder.resolve(mergedNode.Props.Values[index])
		if arrayNode == nil || arrayNode.Type != 9 {
			continue
		}
		for _, itemNode := range arrayNode.Array {
			resourceURL := strings.TrimSpace(decoder.stringValue(decoder.objectValue(itemNode, "url")))
			if !validResourceURL(resourceURL, linkType) {
				continue
			}
			if _, exists := seenURLs[resourceURL]; exists {

View on GitHub (pinned to beaa561337)