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

  1. Verify the file exists with os.Stat(req.Video) and log the resolved absolute path before calling PublishVideo
  2. Use an absolute path to avoid working-directory mismatch, especially inside containers/Docker
  3. Check file permissions (chmod/chown) so the process user can read the file
  4. 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

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.