{"record":{"id":"0f2b4a0e55a5e007","repo":"xpzouying/xiaohongshu-mcp","slug":"qrcode-src-is-empty","errorCode":null,"errorMessage":"qrcode src is empty","messagePattern":"qrcode src is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/login.go","lineNumber":107,"sourceCode":"\nfunc (a *LoginAction) FetchQrcodeImage(ctx context.Context) (string, bool, error) {\n\tpp := a.page.Context(ctx)\n\n\t// 导航到小红书首页，这会触发二维码弹窗\n\tpp.MustNavigate(\"https://www.xiaohongshu.com/explore\").MustWaitLoad()\n\n\ttime.Sleep(2 * time.Second)\n\n\tif exists, _, _ := pp.Has(\".main-container .user .link-wrapper .channel\"); exists {\n\t\treturn \"\", true, nil\n\t}\n\n\tsrc, err := pp.MustElement(\".login-container .qrcode-img\").Attribute(\"src\")\n\tif err != nil {\n\t\treturn \"\", false, errors.Wrap(err, \"get qrcode src failed\")\n\t}\n\tif src == nil || len(*src) == 0 {\n\t\treturn \"\", false, errors.New(\"qrcode src is empty\")\n\t}\n\n\treturn *src, false, nil\n}\n\nfunc (a *LoginAction) WaitForLogin(ctx context.Context) bool {\n\tpp := a.page.Context(ctx)\n\tticker := time.NewTicker(500 * time.Millisecond)\n\tdefer ticker.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn false\n\t\tcase <-ticker.C:\n\t\t\tel, err := pp.Element(\".main-container .user .link-wrapper .channel\")\n\t\t\tif err == nil && el != nil {\n\t\t\t\treturn true","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/login.go#L89-L125","documentation":"FetchQrcodeImage reads the src attribute of the '.login-container .qrcode-img' element; if the attribute is nil or an empty string it returns 'qrcode src is empty' along with false (not expired). It means the QR code image element exists but carries no image URL, so the login QR cannot be fetched.","triggerScenarios":"Calling LoginAction.FetchQrcodeImage (xiaohongshu/login.go:107) when the qrcode img has no src — the QR hasn't been generated yet after page load, the login container is a fallback variant without the expected element, or a verify/interstitial page replaced the login page.","commonSituations":"Fetching the QR immediately after navigation before the login widget finishes initializing; XHS serving a slider-captcha instead of the QR login; DOM changes renaming .qrcode-img so the selector matches a stale/empty placeholder img.","solutions":["Wait for the QR image to finish loading (WaitVisible/WaitRequestIdle) before reading the src attribute","Retry FetchQrcodeImage after a short delay — the src is often populated asynchronously","Capture a screenshot when it fails to see whether a captcha/verify page replaced the login UI","Update the '.login-container .qrcode-img' selector if the site markup changed"],"exampleFix":"// before\nsrc, expired, err := login.FetchQrcodeImage(ctx)\nif err != nil { return err }\n// after\nvar src string\nvar expired bool\nvar err error\nfor i := 0; i < 3; i++ {\n    src, expired, err = login.FetchQrcodeImage(ctx)\n    if err == nil || !strings.Contains(err.Error(), \"qrcode src is empty\") { break }\n    time.Sleep(2 * time.Second)\n}\nif err != nil { return err }","handlingStrategy":"retry","validationCode":"_, err := page.Element(\".login-container .qrcode-img\")\n// only proceed if the element exists; wait if err != nil","typeGuard":null,"tryCatchPattern":"var src string; var err error\nfor i := 0; i < 3; i++ {\n    src, _, err = login.FetchQrcodeImage(ctx)\n    if err == nil || !strings.Contains(err.Error(), \"qrcode src is empty\") { break }\n    time.Sleep(2 * time.Second)\n}\nif err != nil { return err }","preventionTips":["Wait for the login widget to finish initializing before fetching the QR","Retry with delay: src is often set asynchronously","Screenshot on failure to detect captcha pages replacing the QR UI"],"tags":["login","qrcode","dom","xiaohongshu"],"backgroundTag":"qrcode-not-available","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}