fish2018/pansou · error

账号和密码不能为空

Error message

账号和密码不能为空

What it means

doLogin validates inputs before attempting authentication and returns this error when username or password is empty after trimming whitespace. It is a synchronous pre-condition check, so no network call is made.

Solutions

  1. Provide non-empty username and password in the user configuration before calling doLogin
  2. Validate credentials at startup/config-load time and fail fast with a clear message
  3. Trim inputs on the caller side and check for emptiness before invoking login

Example fix

// before
_, _, err := p.doLogin(cfg.Username, cfg.Password, true)
// after
if strings.TrimSpace(cfg.Username) == "" || strings.TrimSpace(cfg.Password) == "" {
    return errors.New("panlian 账号或密码未配置")
}
_, _, err := p.doLogin(cfg.Username, cfg.Password, true)
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(cfg.PanlianUser) == "" || strings.TrimSpace(cfg.PanlianPass) == "" {
    return errors.New("panlian 凭据未配置")
}

Prevention

When it happens

Trigger: Calling p.doLogin("", "", ...) or with a whitespace-only username/password, e.g. when user config fields are blank or only contain spaces.

Common situations: Missing PANLIAN username/password in config file or env; credentials loaded from an empty database record; TrimSpace turning " " into "".

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at plugin/panlian/panlian.go:1063

			time.Sleep(time.Duration(attempt+1) * 200 * time.Millisecond)
			continue
		}
		if err := json.Unmarshal(body, out); err != nil {
			if bytes.Contains(body, []byte("请先登录")) || bytes.Contains(body, []byte("login")) {
				return fmt.Errorf("%w: %s", errLoginRequired, string(body))
			}
			return fmt.Errorf("解析接口响应失败: %w", err)
		}
		return nil
	}

	return lastErr
}

func (p *PanlianPlugin) doLogin(username string, password string, remember bool) (string, *LoginResponse, error) {
	username = strings.TrimSpace(username)
	if username == "" || password == "" {
		return "", nil, fmt.Errorf("账号和密码不能为空")
	}
	jar, _ := cookiejar.New(nil)
	client := &http.Client{
		Timeout: RequestTimeout,
		Jar:     jar,
	}

	// 站点登录只认预先由公开接口建立的 PHPSESSID。
	ctx, cancel := context.WithTimeout(context.Background(), RequestTimeout)
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, DefaultBaseURL+"/api/get_types.php", nil)
	if err != nil {
		cancel()
		return "", nil, err
	}
	p.setPanlianHeaders(req, "", DefaultBaseURL+"/all-videos.php")
	resp, err := client.Do(req)
	if err != nil {
		cancel()

View on GitHub (pinned to beaa561337)