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

  1. Read the wrapped cause (errors.Cause / %v of the error) to find the inner step that actually failed
  2. Re-run with a longer context timeout and verify the publish page fully loads before submit
  3. Re-login / refresh cookies — an expired session often leaves the page in a state where form elements never appear
  4. 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

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.