fish2018/pansou · error

重新登录后scraper实例无效

Error message

重新登录后scraper实例无效

What it means

Internal invariant error: after re-login, the value stored in p.scrapers for user.Hash could not be asserted to a non-nil *cloudscraper.Scraper. The map should only ever contain Scraper instances stored by doLogin/reloginUser.

Solutions

  1. Audit all p.scrapers.Store calls to ensure only *cloudscraper.Scraper values are stored.
  2. Ensure doLogin never returns a nil scraper with a nil error.
  3. Retry the request; if persistent, report as a plugin bug.
  4. Re-login the user from scratch to repopulate a valid scraper.

Example fix

// before (doLogin failure path)
return nil, nil
// after
return nil, fmt.Errorf("login failed") // never return nil scraper with nil error
Defensive patterns

Strategy: type-guard

Type guard

newScraper, ok := scraperVal.(*cloudscraper.Scraper)
if !ok || newScraper == nil {
    return errors.New("invalid scraper stored; force re-login")
}

Prevention

When it happens

Trigger: scraperVal.(*cloudscraper.Scraper) type assertion fails or the asserted pointer is nil — e.g. something stored a different type under the user's hash, or a nil scraper was stored.

Common situations: Code changes introduced another entry type into p.scrapers; a failed login path stored nil; mixing plugin versions sharing the same scraper map.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at plugin/gying/gying.go:2410

		}

		// 尝试重新登录
		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)
		if err != nil {
			return nil, fmt.Errorf("重新登录后搜索仍然失败: %w", err)
		}
		if syncErr := p.syncUserCookiesFromScraper(user, newScraper); syncErr != nil && DebugLog {
			fmt.Printf("[Gying] ⚠️  重登搜索后同步用户 %s Cookie失败: %v\n", user.Username, syncErr)
		}
	}

	return results, err
}

View on GitHub (pinned to beaa561337)