xpzouying/xiaohongshu-mcp · error
小红书发布失败
Error message
小红书发布失败
What it means
PublishVideo wraps any failure from submitPublishVideo with the generic message "小红书发布失败". It is a top-level wrapper meaning the video uploaded fine but the form-fill/submit phase (title, content, tags, schedule, visibility, products, publish click, or success check) failed. Check the wrapped cause chain (pkg/errors) for the real step that broke.
Source
Thrown at xiaohongshu/publish_video.go:68
return &PublishAction{page: pp}, nil
}
// PublishVideo 上传视频并提交
func (p *PublishAction) PublishVideo(ctx context.Context, content PublishVideoContent) error {
if content.VideoPath == "" {
return errors.New("视频不能为空")
}
// 重设超时:.Context(ctx) 会替换掉 NewPublishVideoAction 里 Timeout(300s) 的 deadline
page := p.page.Context(ctx).Timeout(300 * time.Second)
if err := uploadVideo(page, content.VideoPath); err != nil {
return errors.Wrap(err, "小红书上传视频失败")
}
if err := submitPublishVideo(ctx, page, content.Title, content.Content, content.Tags, content.ScheduleTime, content.Visibility, content.Products); err != nil {
return errors.Wrap(err, "小红书发布失败")
}
return nil
}
// uploadVideo 上传单个本地视频
func uploadVideo(page *rod.Page, videoPath string) error {
pp := page.Timeout(5 * time.Minute) // 视频处理耗时更长
if _, err := os.Stat(videoPath); os.IsNotExist(err) {
return errors.Wrapf(err, "视频文件不存在: %s", videoPath)
}
// 寻找文件上传输入框(与图文一致的 class,或退回到 input[type=file])
var fileInput *rod.Element
var err error
fileInput, err = pp.Element(".upload-input")
if err != nil || fileInput == nil {
fileInput, err = pp.Element("input[type='file']")View on GitHub (pinned to 332d196854)
Solutions
- Read the wrapped cause (errors.Cause / %v of the error) to find the inner step that actually failed
- Re-run with a longer context timeout and verify the publish page fully loads before submit
- Re-login / refresh cookies — an expired session often leaves the page in a state where form elements never appear
- Check if xiaohongshu.com changed publish page markup; update CSS selectors like div.d-input input
Example fix
// before
err := action.PublishVideo(ctx, content)
log.Println(err) // 小红书发布失败
// after
if err != nil {
log.Printf("%+v", err) // print full stack to see the inner cause
} Defensive patterns
Strategy: try-catch
Validate before calling
if content.VideoPath == "" { t.Fatal("video path required") }
if _, err := os.Stat(content.VideoPath); err != nil { t.Fatalf("video missing: %v", err) }
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
defer cancel() Try / catch
if err := action.PublishVideo(ctx, content); err != nil {
log.Printf("publish failed: %+v", err) // full stack shows the real failing step
if strings.Contains(fmt.Sprint(errors.Cause(err)), "not found") {
// selectors stale — alert for maintenance
}
} Prevention
- Always log wrapped errors with %+v to expose the underlying cause
- Use a long, never-cancelled context for the whole publish flow
- Keep cookies/session fresh before publishing
- Smoke-test selectors after any known site update
When it happens
Trigger: Any error returned by submitPublishVideo: DOM element for title/content not found, humanize.Type failing, setSchedulePublish/setVisibility/bindProducts/clickPublishButton errors, or waitPublishSuccess timeout (page did not navigate away within 15s).
Common situations: Xiaohongshu changed their publish-page DOM selectors; slow page render caused element lookup timeout; a publish failure dialog appeared so the success navigation never happened; content rejected by platform (sensitive words) keeping the user on the publish page.
Related errors
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/afc052ecb1bff922.
Report an issue: GitHub.