{"record":{"id":"a228c23953160db3","repo":"fish2018/pansou","slug":"loginresp-message-dynamic-remote-login-failure-me","errorCode":null,"errorMessage":"loginResp.Message (dynamic remote login failure message)","messagePattern":"loginResp\\.Message \\(dynamic remote login failure message\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/panlian/panlian.go","lineNumber":1130,"sourceCode":"\t\treturn \"\", nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, err := io.ReadAll(resp.Body)\n\tcancel()\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", nil, fmt.Errorf(\"登录请求失败: HTTP %d\", resp.StatusCode)\n\t}\n\n\tvar loginResp LoginResponse\n\tif err := json.Unmarshal(respBody, &loginResp); err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"解析登录响应失败: %w\", err)\n\t}\n\tif !loginResp.Success {\n\t\treturn \"\", nil, errors.New(strings.TrimSpace(loginResp.Message))\n\t}\n\n\tcookieString := cookiesToString(jar.Cookies(baseURL))\n\tif cookieString == \"\" {\n\t\treturn \"\", nil, fmt.Errorf(\"登录成功但未获取到有效 Cookie\")\n\t}\n\n\treturn cookieString, &loginResp, nil\n}\n\nfunc (p *PanlianPlugin) reloginUser(user *User) error {\n\tpassword, err := p.decryptPassword(user.EncryptedPassword)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcookie, _, err := p.doLogin(user.Username, password, true)\n\tif err != nil {\n\t\tuser.Status = \"expired\"","sourceCodeStart":1112,"sourceCodeEnd":1148,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panlian/panlian.go#L1112-L1148","documentation":"When the remote pan-site login API returns success=false, the plugin wraps loginResp.Message (the remote's own failure text, trimmed) in a plain error. The message is dynamic and comes from the upstream server, so text varies (e.g. wrong password, captcha needed, account locked).","triggerScenarios":"POSTing credentials to the pan-site login endpoint and receiving a JSON body with success=false; also triggered indirectly if json unmarshal of the response fails (separate wrapped error).","commonSituations":"Wrong username/password configured for the pan site; account requires captcha or SMS verification; account temporarily locked; site changed its response schema so Success is false by default.","solutions":["Verify the configured pan-site username/password are correct","Log the trimmed loginResp.Message to see the exact upstream reason and act on it (captcha, lockout, etc.)","Re-test with a manual browser login to confirm the account is not locked or captcha-gated","Check whether the site changed its login API/response format and update LoginResponse parsing"],"exampleFix":"// before\nif !loginResp.Success {\n    return \"\", nil, errors.New(strings.TrimSpace(loginResp.Message))\n}\n// after\nif !loginResp.Success {\n    return \"\", nil, fmt.Errorf(\"pan login failed: %s\", strings.TrimSpace(loginResp.Message))\n}","handlingStrategy":"try-catch","validationCode":"// pre-validate credentials non-empty before calling login\nif user == \"\" || pass == \"\" { return errors.New(\"missing pan credentials\") }","typeGuard":null,"tryCatchPattern":"cookie, links, err := login()\nif err != nil {\n    log.Printf(\"pan login failed: %v\", err) // message is remote's own text\n    return err\n}","preventionTips":["Log the remote Message field for the actual reason","Validate credentials in config before login calls","Watch for site schema changes in LoginResponse"],"tags":["authentication","remote-api","dynamic-message","go"],"backgroundTag":"api-error-response","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}