{"record":{"id":"8a3c8a5c5566e920","repo":"matryer/xbar","slug":"open-plugin-source","errorCode":null,"errorMessage":"open plugin source","messagePattern":"open plugin source","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugins/variables.go","lineNumber":125,"sourceCode":"\t\treturn nil, errors.Wrap(err, \"open vars json file\")\n\t}\n\tdefer f.Close()\n\tb, err := io.ReadAll(io.LimitReader(f, 1_000_000))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar vars map[string]interface{}\n\tif err := json.Unmarshal(b, &vars); err != nil {\n\t\treturn nil, errors.Wrap(err, \"json.Unmarshal\")\n\t}\n\treturn vars, nil\n}\n\nfunc (p *Plugin) loadVariablesFromPluginMetadata() (map[string]interface{}, error) {\n\t// read the plugin metadata for default values\n\tpluginFile, err := os.Open(p.Command)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"open plugin source\")\n\t}\n\tdefer pluginFile.Close()\n\tpluginFileB, err := io.ReadAll(io.LimitReader(pluginFile, 1_000_000))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"read plugin source\")\n\t}\n\tpluginMetadata, err := metadata.Parse(metadata.DebugFunc(p.Debugf), p.CleanFilename(), string(pluginFileB))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"metadata.Parse\")\n\t}\n\tvars := make(map[string]interface{})\n\tfor _, pluginVar := range pluginMetadata.Vars {\n\t\tif pluginVar.Default == \"\" {\n\t\t\t// skip values with no default\n\t\t\tcontinue\n\t\t}\n\t\tvars[pluginVar.Name] = pluginVar.DefaultValue()\n\t}","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/plugins/variables.go#L107-L143","documentation":"loadVariablesFromPluginMetadata (pkg/plugins/variables.go:123-125) wraps os.Open failures on the plugin executable itself (p.Command) with 'open plugin source'. The library reads the plugin's source to parse `<xbar.var>` default variable declarations, so if the executable cannot be opened, defaults cannot be loaded and the error propagates up through loadVariables ('load default vars').","triggerScenarios":"The plugin binary/script was deleted, renamed, or moved after its variables were configured; p.Command contains a stale absolute path (plugin dir moved, e.g. ~/Library/Application Support/xbar changed); permission denied on the executable; running with a working directory where a relative p.Command no longer resolves.","commonSituations":"User updates a plugin (file replaced/removed) while xbar still holds the old path; plugin installed from another user's home directory lacks read permission; plugin uninstalled but xbar tries to rebuild env vars from a stale entry.","solutions":["Verify the path in p.Command exists and is readable: `ls -l <path>`; reinstall the plugin if missing.","Restore read/execute permissions on the plugin file (chmod +rx).","Update or remove the stale plugin entry so xbar stops referencing the old path.","Refresh the plugin list in xbar (refresh menu) so p.Command is re-resolved from the actual installed location."],"exampleFix":"// before\npluginFile, err := os.Open(p.Command)\nif err != nil {\n\treturn nil, errors.Wrap(err, \"open plugin source\")\n}\n// after — guard at call site before loading vars\nif _, err := os.Stat(p.Command); err != nil {\n\treturn nil, nil // plugin gone; no defaults to load\n}\npluginFile, err := os.Open(p.Command)\nif err != nil {\n\treturn nil, errors.Wrap(err, \"open plugin source\")\n}","handlingStrategy":"validation","validationCode":"info, err := os.Stat(p.Command)\nif err != nil {\n\tlog.Printf(\"plugin source %s missing: %v\", p.Command, err)\n} else if info.IsDir() {\n\tlog.Printf(\"plugin source %s is a directory\", p.Command)\n} else if info.Mode().Perm()&0444 == 0 {\n\tlog.Printf(\"plugin source %s is not readable\", p.Command)\n}","typeGuard":null,"tryCatchPattern":"if _, err := os.Stat(p.Command); err != nil {\n\tlog.Printf(\"skipping plugin: source not found: %v\", err)\n\treturn nil // do not attempt to run or load vars\n}\nif err := p.run(); err != nil {\n\tif strings.Contains(err.Error(), \"open plugin source\") {\n\t\tlog.Printf(\"plugin source unreadable, reinstall the plugin: %+v\", err)\n\t}\n}","preventionTips":["Reinstall plugins through the app rather than moving files manually.","Refresh the plugin list after updates so p.Command paths stay current.","Check read/execute permissions when installing plugins from archives.","Clean up uninstall leftovers so stale paths are not referenced."],"tags":["go","filesystem","plugins","missing-file"],"backgroundTag":"plugin-source-not-found","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}