fish2018/pansou · error

构造搜索参数失败

Error message

构造搜索参数失败: %w

What it means

Wraps an error from buildSearchPayload, which JSON-marshals the fixed seroval payload map for the search keyword. In practice stdjson.Marshal of this map[string]interface{} structure essentially never fails (no channels/funcs/cyclic data), so this error is defensive and indicates a marshaling failure of the keyword-containing payload structure.

Solutions

  1. Inspect the wrapped json.Marshal error type (e.g. *json.UnsupportedTypeError) to find the offending value
  2. Verify the keyword passed to buildSearchPayload is a plain string (cleanText output)
  3. If NaN/Inf floats were introduced, sanitize them before marshaling
  4. Upgrade/patch the plugin if a recent change altered the payload structure

Example fix

// before
payload := map[string]interface{}{...}
return stdjson.Marshal(payload)
// after: fail fast with context on which field broke
b, err := stdjson.Marshal(payload)
if err != nil {
    return nil, fmt.Errorf("marshal search payload: %w", err)
}
return b, nil
Defensive patterns

Strategy: validation

Validate before calling

func keywordIsSerializable(kw string) bool {
    _, err := json.Marshal(map[string]interface{}{"query": kw})
    return err == nil
}
if !keywordIsSerializable(keyword) { return errors.New("keyword produces non-serializable payload") }

Type guard

func isPlainString(v interface{}) bool { _, ok := v.(string); return ok }

Try / catch

var typeErr *json.UnsupportedTypeError
if errors.As(err, &typeErr) {
    log.Printf("payload field %s is not JSON-serializable", typeErr.Value)
}

Prevention

When it happens

Trigger: json.Marshal fails while serializing the payload map in buildSearchPayload — only possible if the payload structure or keyword data contains an unsupported type (e.g. NaN/Inf float, channel, func, or cyclic reference injected via a modified keyword path).

Common situations: Practically never hit by users; would appear only after a code change introduced an unsupported value into the payload map, or if keyword handling started embedding non-JSON-serializable data.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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

Appendix: source

Thrown at plugin/xiaokupan/xiaokupan.go:112

	functionID := p.currentServerFunctionID()
	results, err := p.searchWithFunctionID(client, keyword, functionID)
	if err != nil {
		refreshedID, refreshErr := p.refreshServerFunctionID(client, functionID)
		if refreshErr != nil {
			return nil, fmt.Errorf("[%s] 搜索失败: %v;刷新接口标识失败: %w", p.Name(), err, refreshErr)
		}
		results, err = p.searchWithFunctionID(client, keyword, refreshedID)
	}
	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索失败: %w", p.Name(), err)
	}
	return plugin.FilterResultsByKeyword(results, keyword), nil
}

func (p *XiaokupanPlugin) searchWithFunctionID(client *http.Client, keyword, functionID string) ([]model.SearchResult, error) {
	payload, err := buildSearchPayload(keyword)
	if err != nil {
		return nil, fmt.Errorf("构造搜索参数失败: %w", err)
	}

	endpoint := fmt.Sprintf("%s/_serverFn/%s", strings.TrimRight(p.baseURL, "/"), functionID)
	parsedEndpoint, err := url.Parse(endpoint)
	if err != nil {
		return nil, fmt.Errorf("解析搜索地址失败: %w", err)
	}
	query := parsedEndpoint.Query()
	query.Set("payload", string(payload))
	parsedEndpoint.RawQuery = query.Encode()

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, parsedEndpoint.String(), nil)
	if err != nil {
		return nil, fmt.Errorf("创建搜索请求失败: %w", err)
	}

View on GitHub (pinned to beaa561337)