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
- Provide non-empty username and password in the user configuration before calling doLogin
- Validate credentials at startup/config-load time and fail fast with a clear message
- 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
- Validate credential fields at config load / startup
- Never store whitespace-padded credentials; trim on ingest
- Fail fast with a clear config error instead of reaching the login call
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
- username cannot be empty
- token cannot be empty
- login required
- loginResp.Message (dynamic remote login failure message)
- secret cannot be empty
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)