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

  1. Check disk space/quota (df -h) and free space if the disk is full.
  2. Verify dstPath is not an existing directory and remove/replace it.
  3. Check effective permissions/umask and SELinux/AppArmor denials (audit log) on the plugin directory.
  4. 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

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


AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02). Data as JSON: /api/errors/71bca358c6970d11. Report an issue: GitHub.