matryer/xbar · error
only one plugin file supported: found %d.
Error message
only one plugin file supported: found %d.
What it means
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)).
Source
Thrown at pkg/plugins/install.go:111
candidateBaseName := fmt.Sprintf("%03d-%s", count, plugin.Filename)
candidatePath = filepath.Join(i.PluginDir, candidateBaseName)
_, err = os.Stat(candidatePath)
}
if !os.IsNotExist(err) {
return "", err
}
return candidatePath, nil
}
// writePluginFiles iterates through the files defined for the plugin, and
// writes them to the plugin installation directory, and sets the entry point
// to be executable.
func (i Installer) writePluginFiles(dstPath string, plugin metadata.Plugin) error {
if len(plugin.Files) == 0 {
return errors.New("no plugin files")
}
if len(plugin.Files) > 1 {
return errors.Errorf("only one plugin file supported: found %d.", len(plugin.Files))
}
for _, f := range plugin.Files {
pluginFile := dstPath
dir := path.Dir(pluginFile)
if err := os.MkdirAll(dir, 0777); err != nil {
return errors.Wrapf(err, "create directory %s for plugin", dir)
}
writer, err := os.Create(pluginFile)
if err != nil {
return errors.Wrapf(err, "create plugin file %s", f.Path)
}
defer writer.Close()
reader := strings.NewReader(f.Content)
if _, err := io.Copy(writer, reader); err != nil {
return errors.Wrapf(err, "write plugin file %s", f.Path)
}
// If the Filename property of the current file matches the Filename
// property of the plugin, this is the entry point, so set it to beView on GitHub (pinned to d624239058)
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
Example fix
// before (plugin.json)
{ "files": ["main.5m.py", "helper.py"] }
// after
{ "files": ["main.5m.py"] } // helper code inlined into main.5m.py Defensive patterns
Strategy: validation
Validate before calling
// before Install: enforce single-file plugins
if len(plugin.Files) > 1 {
return fmt.Errorf("plugin %q has %d files; only single-file plugins can be installed", plugin.Name, len(plugin.Files))
} Try / catch
// Go
if err := installer.Install(ctx, pluginPath); err != nil {
if strings.Contains(err.Error(), "only one plugin file supported") {
return fmt.Errorf("bundle this plugin into one file before installing: %w", err)
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- no plugin files
- malformed xbar.var format (default not in select options)
- unknown xbar.var type: %s
- error fetching plugin %s: %s
- malformed parameters: missing equals
AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02).
Data as JSON: /api/errors/892d178ba3c2a3a2.
Report an issue: GitHub.