{"record":{"id":"58d264660f83da32","repo":"xpzouying/xiaohongshu-mcp","slug":"s-w-58d264","errorCode":null,"errorMessage":"%s后无法确认状态: %w","messagePattern":"(.+?)后无法确认状态: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/like_favorite.go","lineNumber":79,"sourceCode":"\t\treturn fmt.Errorf(\"未找到交互元素 %s: %w\", selector, err)\n\t}\n\treturn humanize.Click(element)\n}\n\n// stateOf 从交互状态里取目标字段（点赞取 liked，收藏取 collected）。\ntype stateOf func(liked, collected bool) bool\n\n// toggleInteract 点击交互按钮并轮询校验状态是否变为 want；最多两次点击。\n// 到达即成功；始终未变或无法读状态则返回 error——消除\"点了没报错就算成功\"的假阳性。\nfunc (a *interactAction) toggleInteract(ctx context.Context, page *rod.Page, feedID, selector string, want bool, actionType interactActionType, pick stateOf) error {\n\tfor attempt := 1; attempt <= 2; attempt++ {\n\t\tif err := a.performClick(page, selector); err != nil {\n\t\t\treturn fmt.Errorf(\"%s点击失败: %w\", actionType, err)\n\t\t}\n\n\t\tok, err := a.waitInteractState(page, feedID, want, pick, 4*time.Second)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"%s后无法确认状态: %w\", actionType, err)\n\t\t}\n\t\tif ok {\n\t\t\thumanize.Delay(ctx, humanize.AfterInteract)\n\t\t\tlogrus.Infof(\"feed %s %s成功（第%d次点击）\", feedID, actionType, attempt)\n\t\t\treturn nil\n\t\t}\n\t\tlogrus.Warnf(\"feed %s %s第%d次点击后状态未变，重试\", feedID, actionType, attempt)\n\t}\n\treturn fmt.Errorf(\"feed %s %s失败：点击后状态始终未变为预期\", feedID, actionType)\n}\n\n// waitInteractState 轮询 __INITIAL_STATE__ 的交互状态，直到 pick()==want 或超时。\n// 状态回写快则立即返回、慢则等满 timeout。\nfunc (a *interactAction) waitInteractState(page *rod.Page, feedID string, want bool, pick stateOf, timeout time.Duration) (bool, error) {\n\tdeadline := time.Now().Add(timeout)\n\tfor {\n\t\tliked, collected, err := a.getInteractState(page, feedID)\n\t\tif err != nil {","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/like_favorite.go#L61-L97","documentation":"After clicking, toggleInteract polls the note's state for up to 4s to confirm the liked/collected flag became the desired value. If state can't be read at all it throws '<actionType>后无法确认状态: %w'; if it reads but never matches after 2 clicks it reports a mismatch — eliminating false-positive successes.","triggerScenarios":"Click succeeded but the initial-state polling couldn't read the liked/collected field (state JSON shape changed, extraction failed) within the 4s window on both attempts.","commonSituations":"Rate limiting or login expiry causing server to ignore the click; __INITIAL_STATE__ schema change breaking the state reader; very slow network exceeding the 4s poll.","solutions":["Unwrap the cause to distinguish read-failure vs state-never-changed","Verify the account session is valid (an expired session swallows clicks)","Increase the poll timeout or retries for slow networks; update state-reading code if schema changed"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := client.LikeFeed(ctx, feedID)\nif err != nil && strings.Contains(err.Error(), \"无法确认状态\") {\n    // verify manually before assuming success or retrying\n    log.Warnf(\"state unverified for %s: %v\", feedID, err)\n    return err\n}","preventionTips":["Keep sessions valid — expired sessions silently ignore clicks","Allow longer settle time on slow networks before state polling gives up","Treat this error as 'unverified', never as success"],"tags":["interaction","verification","polling"],"backgroundTag":"state-verification-failed","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"}