xpzouying/xiaohongshu-mcp · error

视频文件不存在: %s

Error message

视频文件不存在: %s

What it means

uploadVideo checks os.Stat on the provided VideoPath and wraps the os.IsNotExist error with "视频文件不存在: %s". The library refuses to start a browser upload for a file that is not on local disk. Note the wrapped err from os.Stat may be nil-typed when os.Stat itself succeeds differently; primarily this fires when the path does not exist.

Source

Thrown at xiaohongshu/publish_video.go:78

	// 重设超时:.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']")
		if err != nil || fileInput == nil {
			return errors.New("未找到视频上传输入框")
		}
	}

	fileInput.MustSetFiles(videoPath)

	// 对于视频,等待发布按钮变为可点击即表示处理完成
	btn, err := waitForPublishButtonClickable(pp, 10*time.Minute)
	if err != nil {

View on GitHub (pinned to 332d196854)

Solutions

  1. Verify the file exists with os.Stat at the exact path before calling PublishVideo
  2. Use an absolute path, or resolve it relative to the process working directory
  3. If running in Docker, mount the video directory into the container and use the container-side path
  4. Check for typos and that the file was not deleted/moved between scheduling and publishing

Example fix

// before
action.PublishVideo(ctx, PublishVideoContent{VideoPath: "clip.mp4"})
// after
abs, err := filepath.Abs("clip.mp4")
if err != nil { return err }
if _, err := os.Stat(abs); err != nil { return fmt.Errorf("video missing: %w", err) }
action.PublishVideo(ctx, PublishVideoContent{VideoPath: abs})
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(videoPath)
if err != nil || info.IsDir() {
    return fmt.Errorf("video not usable at %s: %v", videoPath, err)
}

Prevention

When it happens

Trigger: Calling PublishVideo with content.VideoPath pointing to a file that does not exist at publish time — deleted, moved, wrong relative path relative to the process working directory, or a URL instead of a local path.

Common situations: Passing a relative path while the MCP server runs from a different working directory (e.g. Docker container vs host); file cleaned up by a temp-dir purge before publishing; typo in filename; passing a remote URL which os.Stat cannot resolve.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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