matryer/xbar · error
create plugin file %s
Error message
create plugin file %s
What it means
Returned by writePluginFiles when os.Create cannot create the plugin file at dstPath after its directory was successfully created. It wraps the OS error with the file path. Typical causes are permission denied on the newly created directory, quota, or the destination path being a directory.
Source
Thrown at pkg/plugins/install.go:121
// 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 be
// executable.
if f.Filename != plugin.Filename {
continue
}
if err := os.Chmod(pluginFile, 0755); err != nil {
return errors.Wrap(err, "set executable permission on plugin entry point")
}
// write the default variables
plugin, err := metadata.Parse(metadata.DebugfNoop, pluginFile, f.Content)
if err != nil {View on GitHub (pinned to d624239058)
Solutions
- Check disk space/quota (df -h) and free space if the disk is full.
- Verify dstPath is not an existing directory and remove/replace it.
- Check effective permissions/umask and SELinux/AppArmor denials (audit log) on the plugin directory.
- Retry Install after fixing permissions on the plugin directory.
Example fix
// before (dstPath is a directory)
os.MkdirAll(dstPath, 0755)
installer.Install(plugin)
// after
if info, err := os.Stat(dstPath); err == nil && info.IsDir() {
os.RemoveAll(dstPath)
}
installer.Install(plugin) Defensive patterns
Strategy: validation
Validate before calling
func ensureCreateOK(path string) error {
if fi, err := os.Stat(path); err == nil && fi.IsDir() {
return fmt.Errorf("%s is a directory", path)
}
dir := filepath.Dir(path)
f, err := os.CreateTemp(dir, ".create-test")
if err != nil { return err }
f.Close(); os.Remove(f.Name())
return nil
}
// run before Install Try / catch
err := installer.Install(plugin)
if err != nil && strings.Contains(err.Error(), "create plugin file") {
var pe *os.PathError
if errors.As(err, &pe) {
switch {
case os.IsPermission(pe): log.Fatalf("permission denied: %s", pe.Path)
default: log.Fatalf("cannot create %s: %v", pe.Path, pe.Err)
}
}
return err
} Prevention
- Check disk space and quota before installing.
- Ensure dstPath does not collide with an existing directory.
- Verify umask/SELinux policy allows creating executable files in the plugin dir.
- Use a user-owned plugin directory.
When it happens
Trigger: Installer.Install -> writePluginFiles when os.Create(dstPath) fails: directory permissions (0777 masked by umask may still be insufficient if parent changed), dstPath already exists as a directory, disk full, or SELinux/AppArmor denial.
Common situations: Disk quota exceeded in home directory; anti-virus or security policy blocking new executable files; dstPath collides with an existing directory; installing on a full disk.
Related errors
- create directory %s for plugin
- set executable permission on plugin entry point
- write plugin file %s
- write default variables
- ReadDir
AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02).
Data as JSON: /api/errors/71bca358c6970d11.
Report an issue: GitHub.