{"record":{"id":"892d178ba3c2a3a2","repo":"matryer/xbar","slug":"only-one-plugin-file-supported-found-d","errorCode":null,"errorMessage":"only one plugin file supported: found %d.","messagePattern":"only one plugin file supported: found (.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugins/install.go","lineNumber":111,"sourceCode":"\t\tcandidateBaseName := fmt.Sprintf(\"%03d-%s\", count, plugin.Filename)\n\t\tcandidatePath = filepath.Join(i.PluginDir, candidateBaseName)\n\t\t_, err = os.Stat(candidatePath)\n\t}\n\tif !os.IsNotExist(err) {\n\t\treturn \"\", err\n\t}\n\treturn candidatePath, nil\n}\n\n// writePluginFiles iterates through the files defined for the plugin, and\n// writes them to the plugin installation directory, and sets the entry point\n// to be executable.\nfunc (i Installer) writePluginFiles(dstPath string, plugin metadata.Plugin) error {\n\tif len(plugin.Files) == 0 {\n\t\treturn errors.New(\"no plugin files\")\n\t}\n\tif len(plugin.Files) > 1 {\n\t\treturn errors.Errorf(\"only one plugin file supported: found %d.\", len(plugin.Files))\n\t}\n\tfor _, f := range plugin.Files {\n\t\tpluginFile := dstPath\n\t\tdir := path.Dir(pluginFile)\n\t\tif err := os.MkdirAll(dir, 0777); err != nil {\n\t\t\treturn errors.Wrapf(err, \"create directory %s for plugin\", dir)\n\t\t}\n\t\twriter, err := os.Create(pluginFile)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"create plugin file %s\", f.Path)\n\t\t}\n\t\tdefer writer.Close()\n\t\treader := strings.NewReader(f.Content)\n\t\tif _, err := io.Copy(writer, reader); err != nil {\n\t\t\treturn errors.Wrapf(err, \"write plugin file %s\", f.Path)\n\t\t}\n\t\t// If the Filename property of the current file matches the Filename\n\t\t// property of the plugin, this is the entry point, so set it to be","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/plugins/install.go#L93-L129","documentation":"writePluginFiles supports installing exactly one file per plugin. If the plugin metadata declares more than one file, it returns errors.Errorf(\"only one plugin file supported: found %d.\", len(plugin.Files)).","triggerScenarios":"Calling Install with a metadata.Plugin whose Files slice contains 2 or more entries — e.g. multi-file plugins or plugin.json listing extra assets.","commonSituations":"Installing a plugin bundle that ships a script plus a companion library file; plugin authors adding READMEs or assets to the files array; future xbar versions supporting multi-file while this installer does not.","solutions":["Package the plugin as a single self-contained file before installing","Remove extra entries from the files array in plugin.json so only the entry-point script remains","Inline auxiliary library files into the main script","Use a newer installer/registry that supports multi-file plugins if available"],"exampleFix":"// before (plugin.json)\n{ \"files\": [\"main.5m.py\", \"helper.py\"] }\n// after\n{ \"files\": [\"main.5m.py\"] } // helper code inlined into main.5m.py","handlingStrategy":"validation","validationCode":"// before Install: enforce single-file plugins\nif len(plugin.Files) > 1 {\n    return fmt.Errorf(\"plugin %q has %d files; only single-file plugins can be installed\", plugin.Name, len(plugin.Files))\n}","typeGuard":null,"tryCatchPattern":"// Go\nif err := installer.Install(ctx, pluginPath); err != nil {\n    if strings.Contains(err.Error(), \"only one plugin file supported\") {\n        return fmt.Errorf(\"bundle this plugin into one file before installing: %w\", err)\n    }\n    return err\n}","preventionTips":["Prefer single-file, self-contained plugin scripts","Inline helper libraries into the entry-point script","Keep READMEs/assets out of the files array","Check the installer's multi-file support before distributing bundles"],"tags":["plugins","install","validation","limitation"],"backgroundTag":"unsupported-multi-file-plugin","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}