{"record":{"id":"83c272e526817258","repo":"xpzouying/xiaohongshu-mcp","slug":"error-83c272","errorCode":null,"errorMessage":"小红书上传视频失败","messagePattern":"小红书上传视频失败","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/publish_video.go","lineNumber":64,"sourceCode":"\t\treturn nil, errors.Wrap(err, \"切换到上传视频失败\")\n\t}\n\n\ttime.Sleep(1 * time.Second)\n\n\treturn &PublishAction{page: pp}, nil\n}\n\n// PublishVideo 上传视频并提交\nfunc (p *PublishAction) PublishVideo(ctx context.Context, content PublishVideoContent) error {\n\tif content.VideoPath == \"\" {\n\t\treturn errors.New(\"视频不能为空\")\n\t}\n\n\t// 重设超时：.Context(ctx) 会替换掉 NewPublishVideoAction 里 Timeout(300s) 的 deadline\n\tpage := p.page.Context(ctx).Timeout(300 * time.Second)\n\n\tif err := uploadVideo(page, content.VideoPath); err != nil {\n\t\treturn errors.Wrap(err, \"小红书上传视频失败\")\n\t}\n\n\tif err := submitPublishVideo(ctx, page, content.Title, content.Content, content.Tags, content.ScheduleTime, content.Visibility, content.Products); err != nil {\n\t\treturn errors.Wrap(err, \"小红书发布失败\")\n\t}\n\treturn nil\n}\n\n// uploadVideo 上传单个本地视频\nfunc uploadVideo(page *rod.Page, videoPath string) error {\n\tpp := page.Timeout(5 * time.Minute) // 视频处理耗时更长\n\n\tif _, err := os.Stat(videoPath); os.IsNotExist(err) {\n\t\treturn errors.Wrapf(err, \"视频文件不存在: %s\", videoPath)\n\t}\n\n\t// 寻找文件上传输入框（与图文一致的 class，或退回到 input[type=file]）\n\tvar fileInput *rod.Element","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/publish_video.go#L46-L82","documentation":"PublishVideo 流程中 uploadVideo 上传视频文件失败（文件不存在、找不到上传输入框或 SetFiles 失败）时被 Wrap 上抛：视频未能传到发布页，具体原因看错误链底层。","triggerScenarios":"content.VideoPath 指向的文件不存在（os.Stat 失败）；页面找不到 .upload-input 或 input[type='file']；input.SetFiles 失败；视频过大或格式不受支持导致平台处理异常；5 分钟上传超时到期。","commonSituations":"传入的是相对路径而工作目录不对；视频文件在上传前被移动/删除；页面仍在「上传图文」tab 没有视频上传入口（前面切换 tab 失败但被继续执行）；视频编码/分辨率不符合小红书要求；网络慢大文件上传超时。","solutions":["上传前用 os.Stat 校验 VideoPath 存在且转为绝对路径（filepath.Abs），并检查扩展名/大小","确认已完成「上传视频」tab 切换（NewPublishVideoAction 返回成功）再调 PublishVideo","确认视频格式为 mp4/mov 且时长、大小符合平台限制，必要时转码","延长 uploadVideo 的超时（>5 分钟）或改善网络环境后重试"],"exampleFix":"// before\nif err := uploadVideo(page, content.VideoPath); err != nil {\n    return errors.Wrap(err, \"小红书上传视频失败\")\n}\n// after\nabsPath, err := filepath.Abs(content.VideoPath)\nif err != nil {\n    return errors.Wrap(err, \"解析视频路径失败\")\n}\nif fi, statErr := os.Stat(absPath); statErr != nil {\n    return errors.Wrapf(statErr, \"视频文件不存在: %s\", absPath)\n} else if fi.Size() == 0 {\n    return errors.New(\"视频文件为空\")\n}\nif err := uploadVideo(page, absPath); err != nil {\n    return errors.Wrap(err, \"小红书上传视频失败\")\n}","handlingStrategy":"validation","validationCode":"func validateVideo(path string) error {\n    abs, err := filepath.Abs(path)\n    if err != nil {\n        return err\n    }\n    fi, err := os.Stat(abs)\n    if err != nil {\n        return fmt.Errorf(\"视频不存在: %w\", err)\n    }\n    if fi.Size() == 0 {\n        return errors.New(\"视频文件为空\")\n    }\n    if fi.Size() > 2<<30 {\n        return errors.New(\"视频超过平台大小限制\")\n    }\n    ext := strings.ToLower(filepath.Ext(abs))\n    if ext != \".mp4\" && ext != \".mov\" {\n        return fmt.Errorf(\"不支持的视频格式: %s\", ext)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := action.PublishVideo(ctx, content); err != nil {\n    if strings.Contains(err.Error(), \"视频文件不存在\") {\n        return fmt.Errorf(\"请检查 VideoPath 配置: %w\", err)\n    }\n    if strings.Contains(err.Error(), \"未找到视频上传输入框\") {\n        // 页面状态问题：重建 action 后重试一次\n        action, nerr := NewPublishVideoAction(page)\n        if nerr != nil {\n            return nerr\n        }\n        return action.PublishVideo(ctx, content)\n    }\n    return err\n}","preventionTips":["发布前统一做内容预检：路径存在、非空、格式/大小合规","使用绝对路径传入 VideoPath","确保 NewPublishVideoAction 成功后再调用 PublishVideo","上传耗时操作设置充足的 context deadline 并与库内超时协调"],"tags":["upload","file-io","video","go-rod"],"backgroundTag":"file-upload-failed","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"}