xpzouying/xiaohongshu-mcp · error
视频文件不存在或不可访问: %v
Error message
视频文件不存在或不可访问: %v
What it means
After checking non-emptiness, PublishVideo calls os.Stat(req.Video); if that fails (file missing, permission denied, broken symlink), the error is wrapped and returned as '视频文件不存在或不可访问: %v'. The wrapped %v contains the underlying os.Stat error (e.g. 'no such file or directory').
Source
Thrown at service.go:301
return err
}
return action.Publish(ctx, content)
}
// PublishVideo 发布视频(本地文件)
func (s *XiaohongshuService) PublishVideo(ctx context.Context, req *PublishVideoRequest) (*PublishVideoResponse, error) {
// 标题长度校验(小红书限制:最大20个字)
if xhsutil.CalcTitleLength(req.Title) > 20 {
return nil, fmt.Errorf("标题长度超过限制")
}
// 本地视频文件校验
if req.Video == "" {
return nil, fmt.Errorf("必须提供本地视频文件")
}
if _, err := os.Stat(req.Video); err != nil {
return nil, fmt.Errorf("视频文件不存在或不可访问: %v", err)
}
var scheduleTime *time.Time
if req.ScheduleAt != "" {
t, err := time.Parse(time.RFC3339, req.ScheduleAt)
if err != nil {
return nil, fmt.Errorf("定时发布时间格式错误,请使用 ISO8601 格式: %v", err)
}
// 校验定时发布时间范围:1小时至14天
now := time.Now()
minTime := now.Add(1 * time.Hour)
maxTime := now.Add(14 * 24 * time.Hour)
if t.Before(minTime) {
return nil, fmt.Errorf("定时发布时间必须至少在1小时后,当前设置: %s,最早可选: %s",
t.Format("2006-01-02 15:04"), minTime.Format("2006-01-02 15:04"))
}View on GitHub (pinned to 332d196854)
Solutions
- Verify the file exists with os.Stat(req.Video) and log the resolved absolute path before calling PublishVideo
- Use an absolute path to avoid working-directory mismatch, especially inside containers/Docker
- Check file permissions (chmod/chown) so the process user can read the file
- Confirm volume mounts if running in Docker
Example fix
// before
req.Video = "videos/clip.mp4" // relative, fails if CWD differs
// after
abs, err := filepath.Abs("videos/clip.mp4")
if err != nil { return err }
if _, err := os.Stat(abs); err != nil { return fmt.Errorf("video missing: %w", err) }
req.Video = abs Defensive patterns
Strategy: validation
Validate before calling
if fi, err := os.Stat(req.Video); err != nil {
return fmt.Errorf("video file not accessible: %w", err)
} else if fi.IsDir() {
return fmt.Errorf("Video must be a file, got a directory: %s", req.Video)
} Type guard
func videoFileExists(p string) bool {
fi, err := os.Stat(p)
return err == nil && !fi.IsDir()
} Try / catch
resp, err := svc.PublishVideo(ctx, req)
if err != nil && strings.Contains(err.Error(), "视频文件不存在或不可访问") {
return fmt.Errorf("check path/permissions for %s: %w", req.Video, err)
} Prevention
- Convert to and log absolute paths (filepath.Abs) before publishing
- os.Stat the video right before the call to catch races/deletions
- In containers, verify volume mounts and the process user's read permission
- Check the wrapped os.Stat error text: 'no such file' vs 'permission denied' point to different fixes
When it happens
Trigger: Calling PublishVideo with req.Video pointing to a path that does not exist, is inaccessible due to permissions, or is a broken symlink — anything for which os.Stat returns an error.
Common situations: Relative path resolved from a different working directory; file deleted between recording and publishing; container volumes not mounted; running as a different user without read permission.
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/a6c7223ca1b74676.
Report an issue: GitHub.