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
- Verify the file exists with os.Stat at the exact path before calling PublishVideo
- Use an absolute path, or resolve it relative to the process working directory
- If running in Docker, mount the video directory into the container and use the container-side path
- 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
- Pass absolute paths resolved via filepath.Abs
- Stat the file immediately before calling PublishVideo
- Mount video directories explicitly when running in containers
- Avoid passing URLs — download to a local temp file first
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.