fish2018/pansou · error

[ ] API返回错误

Error message

[%s] API返回错误: %s

What it means

The wanou API wraps results in an envelope with a code field; code==1 means success. If the API returns any other code, searchImpl surfaces 'API返回错误' together with the API's own message (apiResponse.Msg). This is an application-level error from the upstream API, not a transport error.

Solutions

  1. Log apiResponse.Msg — it usually states the real cause (token/quota/etc.)
  2. Refresh any token/credentials the API requires
  3. Update the client to the current API version and code semantics
  4. Add special handling (e.g. backoff) if the code indicates rate limiting

Example fix

// before
if apiResponse.Code != 1 {
    return nil, fmt.Errorf("[%s] API返回错误: %s", p.Name(), apiResponse.Msg)
}
// after
if apiResponse.Code != 1 {
    if apiResponse.Code == codeRateLimited {
        time.Sleep(backoff)
        return p.searchImpl(query) // retry once
    }
    return nil, fmt.Errorf("[%s] API返回错误(code=%d): %s", p.Name(), apiResponse.Code, apiResponse.Msg)
}
Defensive patterns

Strategy: try-catch

Try / catch

results, err := plugin.Search(ctx, query)
var apiErr *APIError
if errors.As(err, &apiErr) {
    switch apiErr.Code {
    case codeAuth: refreshTokenAndRetry()
    case codeQuota: backoffAndRetryLater()
    default: log.Errorf("upstream API error: %s", apiErr.Msg)
    }
}

Prevention

When it happens

Trigger: Calling SearchWithResult when the upstream responds with valid JSON but code != 1 — e.g. invalid/missing token, quota exhausted, banned account, deprecated API version, or empty/invalid keyword.

Common situations: API key or session expired; free-tier rate limit reached; the aggregator changed its API contract (old code semantics); keyword contains banned terms; server-side maintenance mode.

Related errors


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

Appendix: source

Thrown at plugin/wanou/wanou.go:159

	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()
	
	// 解析JSON响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("[%s] 读取响应失败: %w", p.Name(), err)
	}
	
	var apiResponse WanouAPIResponse
	if err := json.Unmarshal(body, &apiResponse); err != nil {
		return nil, fmt.Errorf("[%s] 解析JSON响应失败: %w", p.Name(), err)
	}
	
	// 检查API响应状态
	if apiResponse.Code != 1 {
		return nil, fmt.Errorf("[%s] API返回错误: %s", p.Name(), apiResponse.Msg)
	}
	
	// 解析搜索结果
	var results []model.SearchResult
	for _, item := range apiResponse.List {
		if result := p.parseAPIItem(item); result.Title != "" {
			results = append(results, result)
		}
	}
	
	return results, nil
}

// WanouAPIResponse API响应结构
type WanouAPIResponse struct {
	Code      int           `json:"code"`
	Msg       string        `json:"msg"`
	Page      int           `json:"page"`

View on GitHub (pinned to beaa561337)