{"record":{"id":"2d9f71db61a58d3c","repo":"xpzouying/xiaohongshu-mcp","slug":"error-2d9f71","errorCode":null,"errorMessage":"图片不能为空","messagePattern":"图片不能为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/publish.go","lineNumber":75,"sourceCode":"\t\tlogrus.Warnf(\"等待 DOM 稳定出现问题: %v，继续尝试\", err)\n\t}\n\ttime.Sleep(1 * time.Second)\n\n\tif err := mustClickPublishTab(pp, \"上传图文\"); err != nil {\n\t\tlogrus.Errorf(\"点击上传图文 TAB 失败: %v\", err)\n\t\treturn nil, err\n\t}\n\n\ttime.Sleep(1 * time.Second)\n\n\treturn &PublishAction{\n\t\tpage: pp,\n\t}, nil\n}\n\nfunc (p *PublishAction) Publish(ctx context.Context, content PublishImageContent) error {\n\tif len(content.ImagePaths) == 0 {\n\t\treturn errors.New(\"图片不能为空\")\n\t}\n\n\t// 重设超时：.Context(ctx) 会替换掉 NewPublishImageAction 里 Timeout(300s) 的 deadline\n\tpage := p.page.Context(ctx).Timeout(300 * time.Second)\n\n\tif err := uploadImages(page, content.ImagePaths); err != nil {\n\t\treturn errors.Wrap(err, \"小红书上传图片失败\")\n\t}\n\n\ttags := content.Tags\n\tif len(tags) >= 10 {\n\t\tlogrus.Warnf(\"标签数量超过10，截取前10个标签\")\n\t\ttags = tags[:10]\n\t}\n\n\tlogrus.Infof(\"发布内容: title=%s, images=%v, tags=%v, schedule=%v, original=%v, visibility=%s, products=%v\", content.Title, len(content.ImagePaths), tags, content.ScheduleTime, content.IsOriginal, content.Visibility, content.Products)\n\n\tif err := submitPublish(ctx, page, content.Title, content.Content, tags, content.ScheduleTime, content.IsOriginal, content.Visibility, content.Products); err != nil {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/publish.go#L57-L93","documentation":"Publish requires at least one image: PublishImageContent.ImagePaths must be non-empty. If it is, Publish (xiaohongshu/publish.go:75) returns '图片不能为空' before opening/interacting with the page, because XHS image-note publishing cannot proceed without images.","triggerScenarios":"Calling PublishAction.Publish with PublishImageContent{ImagePaths: nil} or an empty slice — typically when the caller built the content struct programmatically from a file list that ended up empty (no downloads succeeded, filter removed all files).","commonSituations":"Image download stage failed earlier so the local paths slice is empty; glob pattern matched no files; caller reused a PublishTextContent-shaped flow and forgot to set ImagePaths; config lists an empty images directory.","solutions":["Validate len(content.ImagePaths) > 0 in the caller before invoking Publish","Check the upstream download/glob step: log how many image paths were collected and abort earlier if zero","Populate ImagePaths with existing local files (verify each file exists) before publishing","Return a clearer upstream error including the source directory so misconfiguration is obvious"],"exampleFix":"// before\nerr := publish.Publish(ctx, content) // content.ImagePaths may be empty\n// after\nif len(content.ImagePaths) == 0 {\n    return fmt.Errorf(\"no images to publish: check download stage and image dir\")\n}\nerr := publish.Publish(ctx, content)","handlingStrategy":"validation","validationCode":"if len(content.ImagePaths) == 0 {\n    return fmt.Errorf(\"no images to publish\")\n}\nfor _, p := range content.ImagePaths {\n    if _, err := os.Stat(p); err != nil {\n        return fmt.Errorf(\"image missing: %s\", p)\n    }\n}","typeGuard":"func canPublish(c xiaohongshu.PublishImageContent) bool {\n    return len(c.ImagePaths) > 0\n}","tryCatchPattern":"if err := publish.Publish(ctx, content); err != nil {\n    if strings.Contains(err.Error(), \"图片不能为空\") {\n        return fmt.Errorf(\"publish aborted: image list empty, check download stage\")\n    }\n    return err\n}","preventionTips":["Validate ImagePaths before building the publish request","Verify downloaded files exist on disk before publishing","Fail fast in the download stage if zero images were collected"],"tags":["validation","publish","images","xiaohongshu"],"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"}