fish2018/pansou · error · errLoginRequired

%w: %s

Error message

%w: %s

What it means

In the panlian video search flow, when the upstream list API (/api/get_videos.php) returns Code == -1 and its message contains '登录' (login), the plugin wraps errLoginRequired with the server message. It signals the panlian cookie/session is no longer valid and re-login is needed.

Solutions

  1. Re-login to panlian and update the stored cookie via the plugin's config/set-cookie command.
  2. Detect errors.Is(err, errLoginRequired) in the caller and prompt the user to refresh credentials instead of retrying.
  3. Check the cookie string for whitespace or quotes when pasting it into config.
  4. Verify the account still works by calling panlian directly in a browser.

Example fix

// before
results, err := p.searchVideos(keyword) // err: login required
// after
if errors.Is(err, plugin.ErrLoginRequired) {
    promptUserToRefreshPanlianCookie()
    return
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling search: check a cookie is configured and non-empty
if strings.TrimSpace(cookie) == "" {
    return fmt.Errorf("panlian cookie not configured; set it before searching")
}

Try / catch

resp, err := plugin.SearchVideos(ctx, keyword)
if errors.Is(err, plugin.ErrLoginRequired) { // panlian wraps errLoginRequired with %w
    refreshPanlianCookieAndRetry()
    return
}
if err != nil { return err }

Prevention

When it happens

Trigger: Calling the search/list API with an expired, revoked, or missing panlian cookie; server invalidates the session (password change, forced logout, session TTL) so Code=-1 with a login-related Msg.

Common situations: Cookie pasted once at setup expired days later; user changed panlian password elsewhere; panlian server restarted and dropped sessions; multiple devices triggering session invalidation.

Related errors


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

Appendix: source

Thrown at plugin/panlian/panlian.go:822

		if truncated {
			break
		}
	}

	return links, strings.Join(summaryParts, " / "), latest, truncated
}

func (p *PanlianPlugin) fetchVideos(client *http.Client, cookie string, keyword string) (*VideoSearchResponse, error) {
	values := url.Values{}
	values.Set("wd", keyword)
	values.Set("pg", "1")

	var resp VideoSearchResponse
	if err := p.doJSONGET(client, cookie, "/api/get_videos.php", values, &resp); err != nil {
		return nil, err
	}
	if resp.Code == -1 && strings.Contains(resp.Msg, "登录") {
		return nil, fmt.Errorf("%w: %s", errLoginRequired, resp.Msg)
	}
	if resp.Code != 1 {
		return nil, fmt.Errorf("盘链列表接口异常: %s", resp.Msg)
	}
	return &resp, nil
}

func (p *PanlianPlugin) fetchPanLinks(client *http.Client, cookie string, keyword string, vodID int) (*PanLinkResponse, error) {
	values := url.Values{}
	values.Set("keyword", keyword)
	values.Set("vod_id", fmt.Sprintf("%d", vodID))
	values.Set("_t", fmt.Sprintf("%d", time.Now().UnixMilli()))

	var resp PanLinkResponse
	if err := p.doJSONGET(client, cookie, "/api/search_pan_links.php", values, &resp); err != nil {
		return nil, err
	}
	if !resp.Success && strings.Contains(resp.Message, "登录") {

View on GitHub (pinned to beaa561337)