xpzouying/xiaohongshu-mcp · error

小红书上传图片失败

Error message

小红书上传图片失败

What it means

Publish uploads the provided image files into the creator publish page via uploadImages (typically rod's file-input setting plus DOM interaction). '小红书上传图片失败' wraps any error from that step: the upload button/input selector wasn't found, a file path doesn't exist or is unreadable, the file dialog/set-files CDP call failed, or the upload stalled. It does not cover later submit failures (those get '小红书发布失败').

Source

Thrown at xiaohongshu/publish.go:82

	}

	time.Sleep(1 * time.Second)

	return &PublishAction{
		page: pp,
	}, nil
}

func (p *PublishAction) Publish(ctx context.Context, content PublishImageContent) error {
	if len(content.ImagePaths) == 0 {
		return errors.New("图片不能为空")
	}

	// 重设超时:.Context(ctx) 会替换掉 NewPublishImageAction 里 Timeout(300s) 的 deadline
	page := p.page.Context(ctx).Timeout(300 * time.Second)

	if err := uploadImages(page, content.ImagePaths); err != nil {
		return errors.Wrap(err, "小红书上传图片失败")
	}

	tags := content.Tags
	if len(tags) >= 10 {
		logrus.Warnf("标签数量超过10,截取前10个标签")
		tags = tags[:10]
	}

	logrus.Infof("发布内容: title=%s, images=%v, tags=%v, schedule=%v, original=%v, visibility=%s, products=%v", content.Title, len(content.ImagePaths), tags, content.ScheduleTime, content.IsOriginal, content.Visibility, content.Products)

	if err := submitPublish(ctx, page, content.Title, content.Content, tags, content.ScheduleTime, content.IsOriginal, content.Visibility, content.Products); err != nil {
		return errors.Wrap(err, "小红书发布失败")
	}

	return nil
}

// hasPopCover 当前页面是否还有挡人的浮层。

View on GitHub (pinned to 332d196854)

Solutions

  1. Validate every path before calling Publish: os.Stat each entry in ImagePaths and convert to absolute paths
  2. Check the wrapped inner error printed by errors.Wrap to see whether it's a selector miss (fix selector) or a file error (fix path)
  3. Convert images to JPEG/PNG under the site's size limit (typically ~32MB each, ≤18 images per post)
  4. Re-run with a longer ctx budget if uploading many large images; Publish resets to a 300s timeout
  5. If a selector miss, dump the upload area HTML and update the input selector in uploadImages

Example fix

// before
err := action.Publish(ctx, content) // ImagePaths: ["./pic/a.jpg"] relative path
// after
for i, p := range content.ImagePaths {
    abs, err := filepath.Abs(p)
    if err != nil || !fileExists(abs) { return fmt.Errorf("image not found: %s", p) }
    content.ImagePaths[i] = abs
}
err := action.Publish(ctx, content)
Defensive patterns

Strategy: validation

Validate before calling

func validateImagePaths(paths []string) error {
    if len(paths) == 0 { return errors.New("images required") }
    for _, p := range paths {
        abs, err := filepath.Abs(p)
        if err != nil { return err }
        info, err := os.Stat(abs)
        if err != nil { return fmt.Errorf("image missing: %s", p) }
        if info.Size() > 32<<20 { return fmt.Errorf("image too large: %s", p) }
    }
    return nil
}

Type guard

func allImagesReadable(paths []string) bool {
    for _, p := range paths {
        f, err := os.Open(p)
        if err != nil { return false }
        f.Close()
    }
    return len(paths) > 0
}

Try / catch

if err := action.Publish(ctx, content); err != nil {
    if strings.Contains(err.Error(), "小红书上传图片失败") {
        // inspect wrapped cause: file path vs selector vs timeout
        log.Printf("upload failed: %+v", err)
    }
    return err
}

Prevention

When it happens

Trigger: content.ImagePaths contains a path that doesn't exist or isn't readable by the browser process; ImagePaths is empty (though that's caught earlier with '图片不能为空'); the upload input selector no longer matches after a site change; the images exceed xiaohongshu's size/count/format limits so the page rejects them; the 300s timeout expires on slow uploads of large files.

Common situations: Passing relative paths when the browser runs in a different working directory or container (headless server); HEIC/oversized images the site refuses; more images than the site's per-post limit; a site redesign moving the upload input so SetFiles can't find it.

Related errors


AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05). Data as JSON: /api/errors/d9aa8e0920455c12. Report an issue: GitHub.