{"record":{"id":"0942d8e87e38c839","repo":"fish2018/pansou","slug":"403-w","errorCode":null,"errorMessage":"403错误且重新登录失败: %w","messagePattern":"403错误且重新登录失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/gying/gying.go","lineNumber":2399,"sourceCode":"\tresults, err := p.searchWithScraper(keyword, scraper)\n\tif err == nil {\n\t\tif syncErr := p.syncUserCookiesFromScraper(user, scraper); syncErr != nil && DebugLog {\n\t\t\tfmt.Printf(\"[Gying] ⚠️  搜索后同步用户 %s Cookie失败: %v\\n\", user.Username, syncErr)\n\t\t}\n\t}\n\n\t// 检测是否为403错误\n\tif err != nil && strings.Contains(err.Error(), \"403\") {\n\t\tif DebugLog {\n\t\t\tfmt.Printf(\"[Gying] ⚠️  检测到403错误，尝试重新登录用户 %s\\n\", user.Username)\n\t\t}\n\n\t\t// 尝试重新登录\n\t\tif reloginErr := p.reloginUser(user); reloginErr != nil {\n\t\t\tif DebugLog {\n\t\t\t\tfmt.Printf(\"[Gying] ❌ 重新登录失败: %v\\n\", reloginErr)\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"403错误且重新登录失败: %w\", reloginErr)\n\t\t}\n\n\t\t// 获取新的scraper实例\n\t\tscraperVal, exists := p.scrapers.Load(user.Hash)\n\t\tif !exists {\n\t\t\treturn nil, fmt.Errorf(\"重新登录后未找到scraper实例\")\n\t\t}\n\n\t\tnewScraper, ok := scraperVal.(*cloudscraper.Scraper)\n\t\tif !ok || newScraper == nil {\n\t\t\treturn nil, fmt.Errorf(\"重新登录后scraper实例无效\")\n\t\t}\n\n\t\t// 使用新scraper重试搜索\n\t\tif DebugLog {\n\t\t\tfmt.Printf(\"[Gying] 🔄 使用新登录状态重试搜索\\n\")\n\t\t}\n\t\tresults, err = p.searchWithScraper(keyword, newScraper)","sourceCodeStart":2381,"sourceCodeEnd":2417,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/gying/gying.go#L2381-L2417","documentation":"Returned when a search request hit HTTP 403 (session expired or Cloudflare challenge) and the automatic re-login via reloginUser also failed. The original relogin error is wrapped so the caller sees both that a 403 occurred and why recovery failed.","triggerScenarios":"searchWithScraper receives a 403 response; the code checks for 403 and calls p.reloginUser(user); reloginUser returns a non-nil error (decrypt or doLogin failure), producing this wrapped error.","commonSituations":"Session cookie expired long ago and stored credentials are also stale/invalid; site is down or challenging so both the original request and the re-login fail; encryption key mismatch causing the decrypt step inside relogin to fail.","solutions":["Fix the underlying relogin error (see the wrapped %w cause): re-save valid credentials.","Check site availability and anti-bot status; retry after it recovers.","Manually refresh the user's cookies/session.","Enable DebugLog to see which step of relogin failed."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-check stored credentials exist before relying on automatic relogin\nif user == nil || user.EncryptedPassword == \"\" {\n    return errors.New(\"cannot auto-relogin: no stored credentials\")\n}","typeGuard":null,"tryCatchPattern":"results, err := p.Search(keyword)\nvar ctxErr *fmt.wrapError\nif err != nil && strings.Contains(err.Error(), \"403\") {\n    // 403 + failed relogin: back off and verify credentials before retrying\n    time.Sleep(retryDelay)\n    results, err = p.Search(keyword)\n}","preventionTips":["Keep valid credentials stored so automatic re-login can succeed.","Persist cookies to reduce 403-triggered re-login frequency.","Monitor site availability before assuming a credential problem."],"tags":["http-403","session-expired","relogin"],"backgroundTag":"http-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"}