matryer/xbar · error
set executable permission on plugin entry point
Error message
set executable permission on plugin entry point
What it means
Returned by writePluginFiles when os.Chmod fails to set mode 0755 on the installed plugin's entry-point file. The chmod makes the entry point executable so it can be invoked later. Failure means the process lacks ownership/permission on the file or the filesystem does not support permission changes.
Source
Thrown at pkg/plugins/install.go:135
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 {
log.Println("install plugin: unable to parse metadata:", err)
}
if len(plugin.Vars) > 0 {
defaultVars := make(map[string]interface{})
for _, pluginVar := range plugin.Vars {
defaultVars[pluginVar.Name] = pluginVar.DefaultValue()
}
err := SaveVariableValues(i.PluginDir, pluginFile, defaultVars)
if err != nil {
return errors.Wrap(err, "write default variables")
}
}
}
return nilView on GitHub (pinned to d624239058)
Solutions
- Ensure the process owns the newly written plugin file (same user created it) and the filesystem supports Unix permissions.
- Verify the file still exists at pluginFile and was not modified concurrently.
- As a workaround, pre-set umask so created files are already executable, or chmod manually after install.
- Check for external interference (AV/indexers) that could remove the file mid-install.
Example fix
// before
installer.Install(plugin) // fails on FAT32 USB mount
// after
pluginDir = filepath.Join(os.Getenv("HOME"), ".upterm", "plugins") // use a native-FS location
installer := plugins.Installer{PluginDir: pluginDir}
installer.Install(plugin) Defensive patterns
Strategy: fallback
Validate before calling
// skip check on filesystems without Unix perms
support := func(dir string) bool {
p := filepath.Join(dir, ".permtest")
os.WriteFile(p, []byte("x"), 0644)
defer os.Remove(p)
err := os.Chmod(p, 0755)
return err == nil
} Try / catch
err := installer.Install(plugin)
if err != nil && strings.Contains(err.Error(), "set executable permission") {
log.Printf("chmod unsupported on this filesystem; set executable bit manually")
// fallback: os.Chmod(pluginFile, 0755) after remount, or relocate PluginDir
return nil
}
return err Prevention
- Install plugins on native Unix filesystems (ext4/APFS), not FAT/exFAT or some network mounts.
- Avoid concurrent processes touching files in PluginDir during install.
- Set a permissive umask so newly written files already carry intended modes.
- If chmod fails manually, set the executable bit after install completes.
When it happens
Trigger: Installer.Install -> writePluginFiles, after writing the file whose f.Filename equals plugin.Filename, when os.Chmod(pluginFile, 0755) returns an error: the file was moved/replaced between create and chmod, filesystem is FAT/exFAT without permission support, or ownership was altered externally.
Common situations: Installing plugins onto a Windows-formatted or network mount that ignores chmod; security software resetting file ownership; concurrent processes manipulating the plugin directory.
Related errors
- create directory %s for plugin
- create plugin file %s
- write plugin file %s
- write default variables
- ReadDir
AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02).
Data as JSON: /api/errors/56fe0341606c64d0.
Report an issue: GitHub.