fish2018/pansou · error

403错误且重新登录失败

Error message

403错误且重新登录失败: %w

What it means

Returned when a search request hit HTTP 403 (session expired or Cloudflare challenge) and the automatic re-login via reloginUser also failed. The original relogin error is wrapped so the caller sees both that a 403 occurred and why recovery failed.

Solutions

  1. Fix the underlying relogin error (see the wrapped %w cause): re-save valid credentials.
  2. Check site availability and anti-bot status; retry after it recovers.
  3. Manually refresh the user's cookies/session.
  4. Enable DebugLog to see which step of relogin failed.
Defensive patterns

Strategy: retry

Validate before calling

// pre-check stored credentials exist before relying on automatic relogin
if user == nil || user.EncryptedPassword == "" {
    return errors.New("cannot auto-relogin: no stored credentials")
}

Try / catch

results, err := p.Search(keyword)
var ctxErr *fmt.wrapError
if err != nil && strings.Contains(err.Error(), "403") {
    // 403 + failed relogin: back off and verify credentials before retrying
    time.Sleep(retryDelay)
    results, err = p.Search(keyword)
}

Prevention

When it happens

Trigger: searchWithScraper receives a 403 response; the code checks for 403 and calls p.reloginUser(user); reloginUser returns a non-nil error (decrypt or doLogin failure), producing this wrapped error.

Common situations: Session cookie expired long ago and stored credentials are also stale/invalid; site is down or challenging so both the original request and the re-login fail; encryption key mismatch causing the decrypt step inside relogin to fail.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

Thrown at plugin/gying/gying.go:2399

	results, err := p.searchWithScraper(keyword, scraper)
	if err == nil {
		if syncErr := p.syncUserCookiesFromScraper(user, scraper); syncErr != nil && DebugLog {
			fmt.Printf("[Gying] ⚠️  搜索后同步用户 %s Cookie失败: %v\n", user.Username, syncErr)
		}
	}

	// 检测是否为403错误
	if err != nil && strings.Contains(err.Error(), "403") {
		if DebugLog {
			fmt.Printf("[Gying] ⚠️  检测到403错误,尝试重新登录用户 %s\n", user.Username)
		}

		// 尝试重新登录
		if reloginErr := p.reloginUser(user); reloginErr != nil {
			if DebugLog {
				fmt.Printf("[Gying] ❌ 重新登录失败: %v\n", reloginErr)
			}
			return nil, fmt.Errorf("403错误且重新登录失败: %w", reloginErr)
		}

		// 获取新的scraper实例
		scraperVal, exists := p.scrapers.Load(user.Hash)
		if !exists {
			return nil, fmt.Errorf("重新登录后未找到scraper实例")
		}

		newScraper, ok := scraperVal.(*cloudscraper.Scraper)
		if !ok || newScraper == nil {
			return nil, fmt.Errorf("重新登录后scraper实例无效")
		}

		// 使用新scraper重试搜索
		if DebugLog {
			fmt.Printf("[Gying] 🔄 使用新登录状态重试搜索\n")
		}
		results, err = p.searchWithScraper(keyword, newScraper)

View on GitHub (pinned to beaa561337)