{"record":{"id":"8adccfcf58f2cc94","repo":"xpzouying/xiaohongshu-mcp","slug":"d-s","errorCode":null,"errorMessage":"翻找 %d 轮仍未定位到评论 %s","messagePattern":"翻找 (.+?) 轮仍未定位到评论 (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/notification_reply.go","lineNumber":135,"sourceCode":"\t\t\t\treturn nil, 0, fmt.Errorf(\"该评论已删除或不可见，不能回复: %s\", commentID)\n\t\t\t}\n\t\t\treturn &r, i, nil\n\t\t}\n\n\t\tif !payload.HasMore {\n\t\t\treturn nil, 0, fmt.Errorf(\"未找到评论 %s，它可能不在「评论和@」里或已被清理\", commentID)\n\t\t}\n\n\t\tif err := page.Mouse.Scroll(0, 800, 5); err != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"滚动查找失败: %w\", err)\n\t\t}\n\t\thumanize.Delay(ctx, humanize.BetweenScroll)\n\n\t\tif err := ctx.Err(); err != nil {\n\t\t\treturn nil, 0, err\n\t\t}\n\t}\n\treturn nil, 0, fmt.Errorf(\"翻找 %d 轮仍未定位到评论 %s\", maxRounds, commentID)\n}\n\n// verifyReplyTarget 用输入框的 placeholder 核对回复对象。\nfunc verifyReplyTarget(input *rod.Element, nickname string) error {\n\tplaceholder, err := input.Attribute(\"placeholder\")\n\tif err != nil || placeholder == nil {\n\t\treturn fmt.Errorf(\"读不到回复框提示文字，无法确认回复对象，已中止\")\n\t}\n\tif nickname != \"\" && !strings.Contains(*placeholder, nickname) {\n\t\treturn fmt.Errorf(\"回复对象不符：期望 %q，实际提示为 %q，已中止\", nickname, *placeholder)\n\t}\n\treturn nil\n}\n\n// waitReplyAccepted 等待回复提交完成。\nfunc waitReplyAccepted(item *rod.Element, timeout time.Duration) error {\n\tdeadline := time.Now().Add(timeout)\n\tfor time.Now().Before(deadline) {","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/notification_reply.go#L117-L153","documentation":"locate() caps the scroll-and-search loop at maxRounds=20. If the commentID is still not found after 20 iterations — and HasMore stayed true each time so the earlier 'not found / cleaned' branch never fired — it gives up with this error. It means the comment exists deeper than 20 scroll-screens or pagination never terminates.","triggerScenarios":"Reply/Like with a valid but very old commentID buried hundreds of notifications deep; a platform quirk where payload.HasMore never becomes false, so the loop runs all 20 rounds without a definitive answer.","commonSituations":"Accounts with very active notification feeds (the target scrolled out quickly); replying to comments older than a few weeks on busy accounts; virtualized list rendering where old items get recycled before they are matched.","solutions":["Increase maxRounds if you must reach deep history (accepting longer runtime and more detection risk)","Use the XHS web/API notification pagination directly to page to the comment instead of scrolling","Fall back to locating the comment on its note page and replying there","For old comments, prefer replying promptly — treat >1 week old comments as high-risk for this error"],"exampleFix":"// before\nconst maxRounds = 20\n// after\n// page via readTab pagination (offset cursor) instead of mouse scroll:\nfor payload.HasMore {\n    payload = n.readTabPage(page, TabMentions, cursor); cursor++\n    if r, i := match(payload, commentID); r != nil { return r, i, nil }\n}","handlingStrategy":"fallback","validationCode":"// skip clearly-stale comments before invoking the deep scroll\nif time.Since(commentCreatedAt) > 7*24*time.Hour {\n    return fmt.Errorf(\"skip: comment %s too old for notification-reply flow\", commentID)\n}","typeGuard":null,"tryCatchPattern":"_, err := action.Reply(ctx, commentID, content)\nif err != nil && strings.Contains(err.Error(), \"翻找\") {\n    log.Printf(\"deep-scroll miss for %s; falling back to note-page reply\", commentID)\n    return replyViaNotePage(ctx, feedID, commentID, content)\n}","preventionTips":["Reply to comments promptly; don't queue them for days on busy accounts","Keep a fallback reply path via the note page","Cap retries — this error means the target wasn't reachable, not a transient fault"],"tags":["browser-automation","go","pagination","timeout"],"backgroundTag":"element-not-found-after-pagination","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}