{"record":{"id":"4a7e6117597ddd04","repo":"xpzouying/xiaohongshu-mcp","slug":"error-4a7e61","errorCode":null,"errorMessage":"获取正文长度文本失败","messagePattern":"获取正文长度文本失败","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/publish.go","lineNumber":629,"sourceCode":"\t\treturn errors.Wrap(err, \"获取标题长度文本失败\")\n\t}\n\n\treturn makeMaxLengthError(titleLength)\n}\n\nfunc checkContentMaxLength(page *rod.Page) error {\n\thas, elem, err := page.Has(`div.edit-container div.length-error`)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"检查正文长度元素失败\")\n\t}\n\n\tif !has {\n\t\treturn nil\n\t}\n\n\tcontentLength, err := elem.Text()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"获取正文长度文本失败\")\n\t}\n\n\treturn makeMaxLengthError(contentLength)\n}\n\nfunc makeMaxLengthError(elemText string) error {\n\tparts := strings.Split(elemText, \"/\")\n\tif len(parts) != 2 {\n\t\treturn errors.Errorf(\"长度超过限制: %s\", elemText)\n\t}\n\n\tcurrLen, maxLen := parts[0], parts[1]\n\n\treturn errors.Errorf(\"当前输入长度为%s，最大长度为%s\", currLen, maxLen)\n}\n\n// contentElemSelectors 正文输入框的候选选择器，按先后顺序尝试。\nvar contentElemSelectors = []string{","sourceCodeStart":611,"sourceCodeEnd":647,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/publish.go#L611-L647","documentation":"This error wraps a failure to read the text of the body-length indicator element (div.edit-container div.length-error) via elem.Text() during publish validation. The library throws it when the Xiaohongshu creator page shows a length-error badge but its text content cannot be fetched from the DOM (element detached, page navigated, or CDP call failed). It is an intermediate wrap: the caller checkContentMaxLength detects the over-length UI element and needs its text to build the final length message.","triggerScenarios":"submitPublish calls checkContentMaxLength after filling content; page.Has finds div.edit-container div.length-error, but elem.Text() fails — typically because the page re-rendered and the element was removed between Has() and Text(), the tab was closed/navigated, or the CDP session errored.","commonSituations":"Slow or flaky network causing DOM churn during publish; Xiaohongshu front-end update that replaces the length-error node after detection; user closes the browser tab mid-publish; browser automation session interrupted (timeout, context cancelled).","solutions":["Retry the publish flow — the error is usually transient DOM churn; checkContentMaxLength is re-evaluated on each attempt.","Shorten the content before publishing so the length-error element never appears and elem.Text() is never called.","Update selectors/page handling if the site DOM changed; re-check div.edit-container div.length-error still exists with a stable text node.","Ensure the browser page stays open and no concurrent navigation occurs during publish."],"exampleFix":"// before\nhas, elem, err := page.Has(`div.edit-container div.length-error`)\n...\ncontentLength, err := elem.Text()\n// after\nhas, elem, err := page.Has(`div.edit-container div.length-error`)\n...\n// retry text read to survive transient DOM churn\nvar contentLength string\nfor i := 0; i < 3; i++ {\n    if contentLength, err = elem.Text(); err == nil {\n        break\n    }\n    time.Sleep(200 * time.Millisecond)\n}","handlingStrategy":"retry","validationCode":"// pre-check content length in Go before publishing so the over-length badge never appears\nif utf8.RuneCountInString(content) > 1000 {\n    return fmt.Errorf(\"正文长度 %d 超过最大 1000\", utf8.RuneCountInString(content))\n}","typeGuard":"func hasLengthError(page *rod.Page) bool {\n    has, _, err := page.Has(`div.edit-container div.length-error`)\n    return err == nil && has\n}","tryCatchPattern":"err := publisher.Publish(ctx, opts)\nif err != nil && strings.Contains(err.Error(), \"获取正文长度文本失败\") {\n    // transient DOM churn: retry once with a fresh page state\n    time.Sleep(time.Second)\n    err = publisher.Publish(ctx, opts)\n}","preventionTips":["Validate title/content rune counts against site limits before calling publish","Keep the tab open and avoid concurrent navigation during publish","Retry transient DOM-read failures with a short backoff","Pin/selectors-check after known site front-end updates"],"tags":["browser-automation","dom","rod","xiaohongshu"],"backgroundTag":"element-text-extraction-failed","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"}