{"record":{"id":"ee432d5c83b6ad82","repo":"matryer/xbar","slug":"missing-xbar-image","errorCode":null,"errorMessage":"missing xbar.image","messagePattern":"missing xbar\\.image","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/metadata/plugin_metadata.go","lineNumber":77,"sourceCode":"\tLastUpdated time.Time `json:\"lastUpdated\"`\n\t// Vars are the configurable values for this Plugin.\n\tVars []PluginVar `json:\"vars\"`\n\n\t// ProcessingNotes is a list of errors/warnings/notes that are set during\n\t// the processing of this plugin.\n\tProcessingNotes []string `json:\"processingNotes\"`\n}\n\n// Validate checks the plugin data.\nfunc (p Plugin) Validate() error {\n\tif p.Title == \"\" {\n\t\treturn errors.New(\"missing xbar.title\")\n\t}\n\tif p.Desc == \"\" {\n\t\treturn errors.New(\"missing xbar.desc\")\n\t}\n\tif !HasImage(p.ImageURL) {\n\t\treturn errors.New(\"missing xbar.image\")\n\t}\n\tif len(p.Authors) == 0 {\n\t\treturn errors.New(\"missing xbar.author\")\n\t}\n\treturn nil // ok\n}\n\n// NiceDesc gets a nice description.\nfunc (p Plugin) NiceDesc() string {\n\tif p.Desc == \"\" {\n\t\treturn p.Title\n\t}\n\treturn truncate(p.Desc, 75)\n}\n\n// File is a single file.\ntype File struct {\n\t// Path is the path of the File.","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/metadata/plugin_metadata.go#L59-L95","documentation":"Plugin.Validate requires the plugin to have a usable image, checked via HasImage(p.ImageURL). The image is the plugin's screenshot/preview in the xbar directory, so a plugin without one fails validation.","triggerScenarios":"Plugin.Validate called on a Plugin whose ImageURL is empty or otherwise fails HasImage — the script has no <xbar.image>...</xbar.image> comment or the URL inside is blank/invalid.","commonSituations":"Author skipped adding a screenshot; image URL points to a private or deleted asset so it was treated as missing; image comment removed by a linter; programmatically built Plugin with ImageURL unset.","solutions":["Add an <xbar.image>https://.../screenshot.png</xbar.image> comment block pointing to a public image","Set the ImageURL field (a value HasImage accepts) before Validate","Host the screenshot somewhere publicly reachable (e.g. GitHub) and re-parse"],"exampleFix":"// before (plugin script metadata)\n// <xbar.image></xbar.image>\n// after\n// <xbar.image>https://raw.githubusercontent.com/user/repo/main/screenshot.png</xbar.image>","handlingStrategy":"validation","validationCode":"func hasImageURL(p metadata.Plugin) bool {\n\treturn strings.TrimSpace(p.ImageURL) != \"\" &&\n\t\t(p.ImageURL[:4] == \"http\" || p.ImageURL[:3] == \"data\")\n}","typeGuard":"func hasValidImage(p metadata.Plugin) bool {\n\treturn p.ImageURL != \"\" // mirrors metadata.HasImage\n}","tryCatchPattern":"if err := plugin.Validate(); err != nil {\n\tif err.Error() == \"missing xbar.image\" {\n\t\treturn fmt.Errorf(\"plugin %s: add an <xbar.image> comment with a public screenshot URL: %w\", path, err)\n\t}\n\treturn err\n}","preventionTips":["Commit a screenshot to the plugin repo and reference it via a raw.githubusercontent URL","Verify the image URL is publicly reachable (no auth-required hosts)","Never leave the <xbar.image> value empty","Check HasImage in CI before submitting to the directory"],"tags":["metadata","validation","plugin","image","go"],"backgroundTag":"missing-metadata-field","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}