{"record":{"id":"d0660162a4037c87","repo":"xpzouying/xiaohongshu-mcp","slug":"error-d06601","errorCode":null,"errorMessage":"必须提供本地视频文件","messagePattern":"必须提供本地视频文件","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service.go","lineNumber":298,"sourceCode":"\n\taction, err := xiaohongshu.NewPublishImageAction(page)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn action.Publish(ctx, content)\n}\n\n// PublishVideo 发布视频（本地文件）\nfunc (s *XiaohongshuService) PublishVideo(ctx context.Context, req *PublishVideoRequest) (*PublishVideoResponse, error) {\n\t// 标题长度校验（小红书限制：最大20个字）\n\tif xhsutil.CalcTitleLength(req.Title) > 20 {\n\t\treturn nil, fmt.Errorf(\"标题长度超过限制\")\n\t}\n\n\t// 本地视频文件校验\n\tif req.Video == \"\" {\n\t\treturn nil, fmt.Errorf(\"必须提供本地视频文件\")\n\t}\n\tif _, err := os.Stat(req.Video); err != nil {\n\t\treturn nil, fmt.Errorf(\"视频文件不存在或不可访问: %v\", err)\n\t}\n\n\tvar scheduleTime *time.Time\n\tif req.ScheduleAt != \"\" {\n\t\tt, err := time.Parse(time.RFC3339, req.ScheduleAt)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"定时发布时间格式错误，请使用 ISO8601 格式: %v\", err)\n\t\t}\n\n\t\t// 校验定时发布时间范围：1小时至14天\n\t\tnow := time.Now()\n\t\tminTime := now.Add(1 * time.Hour)\n\t\tmaxTime := now.Add(14 * 24 * time.Hour)\n\n\t\tif t.Before(minTime) {","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/service.go#L280-L316","documentation":"PublishVideo requires req.Video to be a non-empty path to a local video file. An empty string is rejected immediately with this error before any file system access. The library does not support URL-based video inputs in this code path.","triggerScenarios":"Calling PublishVideo with req.Video == \"\" — e.g. the caller intended URL publishing, forgot to populate the field, or a previous download step silently failed.","commonSituations":"Config field left blank; upstream pipeline produced no local video; confusion between PublishContent (images) and PublishVideo (local file) request contracts.","solutions":["Set req.Video to the absolute path of an existing local video file before calling PublishVideo","If the source is remote, download it to a local file first, then pass that path","Validate req.Video != \"\" in the handler and return a user-facing message early"],"exampleFix":"// before\nreq := &PublishVideoRequest{Title: t} // Video empty\n// after\nreq := &PublishVideoRequest{Title: t, Video: \"/data/videos/clip.mp4\"}","handlingStrategy":"validation","validationCode":"if req.Video == \"\" {\n    return errors.New(\"Video: a local video file path is required\")\n}","typeGuard":"func hasLocalVideo(req *PublishVideoRequest) bool {\n    return req != nil && req.Video != \"\"\n}","tryCatchPattern":"resp, err := svc.PublishVideo(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"必须提供本地视频文件\") {\n    return fmt.Errorf(\"video field empty — pass a local file path: %w\", err)\n}","preventionTips":["Validate required fields (Title, Video) at the handler boundary before calling the service","Keep PublishVideoRequest and PublishRequest contracts distinct — Video is local-path-only","If the source is remote, download to disk first and set Video to that path"],"tags":["go","validation","video","missing-argument"],"backgroundTag":"missing-required-field","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}