helm/helm · error
failed to uninstall plugin %s, got error (%w)
Error message
failed to uninstall plugin %s, got error (%w)
What it means
`helm plugin uninstall NAME...` removes each plugin's directory with os.RemoveAll, deletes cached versioned tarballs, and runs the plugin's delete hook (pkg/cmd/plugin_uninstall.go:87-122). Any per-plugin failure is collected and the batch is returned via errors.Join, so one bad plugin does not stop the others but the command still fails overall. Note a missing plugin produces the distinct 'plugin: %s not found' error instead.
Source
Thrown at pkg/cmd/plugin_uninstall.go:73
func (o *pluginUninstallOptions) complete(args []string) error {
if len(args) == 0 {
return errors.New("please provide plugin name to uninstall")
}
o.names = args
return nil
}
func (o *pluginUninstallOptions) run(out io.Writer) error {
slog.Debug("loading installer plugins", "dir", settings.PluginsDirectory)
plugins, err := plugin.LoadAllDir(settings.PluginsDirectory, plugin.LogIgnorePluginLoadErrorFilterFunc)
if err != nil {
return err
}
var errorPlugins []error
for _, name := range o.names {
if found := findPlugin(plugins, name); found != nil {
if err := uninstallPlugin(found); err != nil {
errorPlugins = append(errorPlugins, fmt.Errorf("failed to uninstall plugin %s, got error (%w)", name, err))
} else {
fmt.Fprintf(out, "Uninstalled plugin: %s\n", name)
}
} else {
errorPlugins = append(errorPlugins, fmt.Errorf("plugin: %s not found", name))
}
}
if len(errorPlugins) > 0 {
return errors.Join(errorPlugins...)
}
return nil
}
func uninstallPlugin(p plugin.Plugin) error {
if err := os.RemoveAll(p.Dir()); err != nil {
return err
}
View on GitHub (pinned to 2a29f1770b)
Solutions
- Fix ownership of the plugins directory (sudo chown -R $(id -u):$(id -g) $HELM_PLUGINS) or re-run the uninstall with sudo
- If the directory is stuck, remove it manually (rm -rf $HELM_PLUGINS/<name>) and confirm with `helm plugin list`
- For hook failures, inspect the plugin's delete hook script and run it manually to see its error
Example fix
# before helm plugin uninstall my-plugin # error: failed to uninstall plugin my-plugin, got error (unlinkat ...: permission denied) # after sudo chown -R "$(id -u):$(id -g)" "$(helm env HELM_PLUGINS)" helm plugin uninstall my-plugin
Defensive patterns
Strategy: try-catch
Validate before calling
func canRemovePluginDir(dir string) error {
fi, err := os.Stat(dir)
if err != nil {
return err
}
if !fi.IsDir() {
return nil
}
probe := filepath.Join(dir, ".rm-probe")
if err := os.WriteFile(probe, nil, 0o644); err != nil {
return fmt.Errorf("no write access to %s (owned by another user?): %w", dir, err)
}
return os.Remove(probe)
} Try / catch
if err := runPluginUninstall(names); err != nil {
// errors.Join bundles per-plugin failures; split them for reporting
type unwrapper interface{ Unwrap() []error }
if u, ok := err.(unwrapper); ok {
for _, e := range u.Unwrap() {
log.Print(e) // handle each plugin independently (permissions vs not-found vs hook)
}
}
return err
} Prevention
- Install and uninstall plugins as the same user so the plugins directory stays owned by that user
- On Windows, stop processes using plugin binaries before uninstalling
- Test delete hooks before shipping a plugin; a failing hook fails the whole uninstall
When it happens
Trigger: Plugins directory owned by root while running as a normal user (os.RemoveAll permission denied); a file inside the plugin dir held open (Windows locks, running plugin process); the plugin's delete hook script exiting non-zero.
Common situations: Plugin installed with sudo but uninstalled without; manually placed plugins with odd ownership; antivirus or editors locking shared libraries during removal.
Related errors
- failed to create cache directory: %w
- failed to create tarball: %w
- error reading %s: %w
- cannot read %s in directory %q
- stat %s: %w
AI-assisted analysis of helm/helm@2a29f1770b (2026-08-15).
Data as JSON: /api/errors/0a1811d581345251.
Report an issue: GitHub.