{"record":{"id":"dbd05e1d2d029915","repo":"fish2018/pansou","slug":"code-d-s","errorCode":null,"errorMessage":"登录失败: code=%d, 响应=%s","messagePattern":"登录失败: code=(.+?), 响应=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/gying/gying.go","lineNumber":2213,"sourceCode":"\t\tparsed, err := strconv.Atoi(codeStr)\n\t\tif err != nil {\n\t\t\tif DebugLog {\n\t\t\t\tfmt.Printf(\"[Gying] 无法解析code字段: %T, 值: %v, 错误: %v\\n\", codeInterface, codeInterface, err)\n\t\t\t}\n\t\t\treturn nil, \"\", fmt.Errorf(\"无法解析code字段，类型: %T, 值: %v\", codeInterface, codeInterface)\n\t\t}\n\t\tcodeValue = parsed\n\t}\n\n\tif DebugLog {\n\t\tfmt.Printf(\"[Gying] 解析后的code值: %d\\n\", codeValue)\n\t}\n\n\tif codeValue != 200 {\n\t\tif DebugLog {\n\t\t\tfmt.Printf(\"[Gying] 登录失败: code=%d (期望200)\\n\", codeValue)\n\t\t}\n\t\treturn nil, \"\", fmt.Errorf(\"登录失败: code=%d, 响应=%s\", codeValue, string(body))\n\t}\n\n\t// ========== 步骤3: GET详情页 (触发防爬cookies如vrg_sc、vrg_go等) ==========\n\tif DebugLog {\n\t\tfmt.Printf(\"[Gying] 步骤3: GET详情页收集完整Cookie\\n\")\n\t}\n\n\t_, warmupStatus, warmupHeaders, err := p.requestWithChallengeRetry(scraper, http.MethodGet, p.getWarmupDetailURL(), \"\", \"\")\n\tif err == nil {\n\t\tif DebugLog {\n\t\t\tfmt.Printf(\"[Gying] 详情页状态码: %d\\n\", warmupStatus)\n\t\t}\n\t\t// 从详情页响应中收集cookies\n\t\tcollectSetCookies(warmupHeaders, cookieMap)\n\t\tlogSetCookiesForDebug(warmupHeaders, \"[Gying]   详情页Cookie: %s=%s\\n\", 30)\n\t}\n\n\t// 构建cookie字符串","sourceCodeStart":2195,"sourceCodeEnd":2231,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/gying/gying.go#L2195-L2231","documentation":"gying treats the login POST's JSON 'code' field as the business-level success signal, requiring exactly 200. Any other value (wrong password, account locked, captcha required, server-side rejection) yields '登录失败: code=%d, 响应=%s', including the raw response body so the caller can see the server's message.","triggerScenarios":"Login step 2 parsed successfully but loginResp[\"code\"] != 200 — e.g. 401/400-style codes for bad credentials, risk-control codes, or any non-200 business code returned by the site's login API.","commonSituations":"Wrong username/password after a password change; account banned or requiring captcha/2FA; site changed its success code convention; submitting credentials to a stale endpoint that answers with an error code.","solutions":["Read the 响应 payload in the error to find the server's message and the actual code value.","Re-check credentials; re-enter or reset the password if the code indicates auth rejection.","Check whether the account requires captcha/2FA/verification — the plugin cannot complete such logins automatically.","Try logging in via a browser to confirm account status (locked, expired, region-blocked).","If the site changed its API contract, update the plugin's expected success code."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// check credentials and account state before invoking login\nif user == \"\" || pass == \"\" {\n    return errors.New(\"credentials required before login\")\n}\n// treat any returned non-200 code as an auth problem, not a bug","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store credentials securely and verify them after password changes.","Handle captcha/2FA accounts outside the automated flow.","Don't retry blindly on auth-rejection codes — retrying wrong credentials risks lockout.","Read the embedded response body to identify risk-control or captcha codes."],"tags":["login","auth","api","credentials"],"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"}