xpzouying/xiaohongshu-mcp · error
翻找 %d 轮仍未定位到评论 %s
Error message
翻找 %d 轮仍未定位到评论 %s
What it means
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.
Source
Thrown at xiaohongshu/notification_reply.go:135
return nil, 0, fmt.Errorf("该评论已删除或不可见,不能回复: %s", commentID)
}
return &r, i, nil
}
if !payload.HasMore {
return nil, 0, fmt.Errorf("未找到评论 %s,它可能不在「评论和@」里或已被清理", commentID)
}
if err := page.Mouse.Scroll(0, 800, 5); err != nil {
return nil, 0, fmt.Errorf("滚动查找失败: %w", err)
}
humanize.Delay(ctx, humanize.BetweenScroll)
if err := ctx.Err(); err != nil {
return nil, 0, err
}
}
return nil, 0, fmt.Errorf("翻找 %d 轮仍未定位到评论 %s", maxRounds, commentID)
}
// verifyReplyTarget 用输入框的 placeholder 核对回复对象。
func verifyReplyTarget(input *rod.Element, nickname string) error {
placeholder, err := input.Attribute("placeholder")
if err != nil || placeholder == nil {
return fmt.Errorf("读不到回复框提示文字,无法确认回复对象,已中止")
}
if nickname != "" && !strings.Contains(*placeholder, nickname) {
return fmt.Errorf("回复对象不符:期望 %q,实际提示为 %q,已中止", nickname, *placeholder)
}
return nil
}
// waitReplyAccepted 等待回复提交完成。
func waitReplyAccepted(item *rod.Element, timeout time.Duration) error {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {View on GitHub (pinned to 332d196854)
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
Example fix
// before
const maxRounds = 20
// after
// page via readTab pagination (offset cursor) instead of mouse scroll:
for payload.HasMore {
payload = n.readTabPage(page, TabMentions, cursor); cursor++
if r, i := match(payload, commentID); r != nil { return r, i, nil }
} Defensive patterns
Strategy: fallback
Validate before calling
// skip clearly-stale comments before invoking the deep scroll
if time.Since(commentCreatedAt) > 7*24*time.Hour {
return fmt.Errorf("skip: comment %s too old for notification-reply flow", commentID)
} Try / catch
_, err := action.Reply(ctx, commentID, content)
if err != nil && strings.Contains(err.Error(), "翻找") {
log.Printf("deep-scroll miss for %s; falling back to note-page reply", commentID)
return replyViaNotePage(ctx, feedID, commentID, content)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/8adccfcf58f2cc94.
Report an issue: GitHub.