asdf-vm/asdf · error
unable to check if plugin already exists: %w
Error message
unable to check if plugin already exists: %w
What it means
Plugin.Add checks PluginExists(dataDir, pluginName) before cloning; if that check itself returns an error, it is wrapped as 'unable to check if plugin already exists'. The add operation aborts because asdf cannot safely determine whether the plugin is already installed — usually a filesystem/stat problem on the data dir.
Source
Thrown at internal/plugins/plugins.go:369
})
}
}
}
return plugins, nil
}
// Add takes plugin name and Git URL and installs the plugin if it isn't
// already installed
func Add(config config.Config, pluginName, pluginURL, ref string) error {
err := validatePluginName(pluginName)
if err != nil {
return err
}
exists, err := PluginExists(config.DataDir, pluginName)
if err != nil {
return fmt.Errorf("unable to check if plugin already exists: %w", err)
}
if exists {
return NewPluginAlreadyExists(pluginName)
}
plugin := New(config, pluginName)
if pluginURL == "" {
// Ignore error here as the default value is fine
disablePluginIndex, _ := config.DisablePluginShortNameRepository()
if disablePluginIndex {
return fmt.Errorf("Short-name plugin repository is disabled")
}
lastCheckDuration := 0
// We don't care about errors here as we can use the default valueView on GitHub (pinned to 074a1722ca)
Solutions
- Inspect the wrapped underlying error — it names the actual OS failure (path, errno).
- Fix permissions/ownership on the data dir (mkdir -p, chown -R).
- Verify ASDF_DATA_DIR points to a valid, accessible directory.
- Remove any regular file occupying a path component that should be a directory.
Example fix
// before: parent path is a file ~/.asdf/plugins exists as a regular file # Error: unable to check if plugin already exists: ... // after rm "$HOME/.asdf/plugins" # remove the offending file mkdir -p "$HOME/.asdf/plugins"
Defensive patterns
Strategy: validation
Validate before calling
dataDir := conf.DataDir
if fi, err := os.Stat(dataDir); err != nil || !fi.IsDir() {
if err := os.MkdirAll(dataDir, 0o755); err != nil {
return fmt.Errorf("data dir unusable: %w", err)
}
}
// probe writability of plugins path before Add
probe := filepath.Join(dataDir, "plugins", ".probe")
os.MkdirAll(filepath.Dir(probe), 0o755)
if err := os.WriteFile(probe, nil, 0o644); err != nil {
return err
}
os.Remove(probe) Try / catch
if err := plugins.Add(conf, pluginName, repoURL); err != nil {
if strings.Contains(err.Error(), "unable to check if plugin already exists") {
log.Printf("fix data dir access (%s): %v", conf.DataDir, err)
}
} Prevention
- Verify ASDF_DATA_DIR exists, is a directory, and is writable at startup.
- chown the data dir to the running user after privileged installs.
- Ensure no regular file occupies paths that should be directories (e.g. plugins/).
- Avoid network-mounted data dirs that can disappear mid-command.
When it happens
Trigger: Calling Add (or `asdf plugin add <name>`) when PluginExists fails: the data dir path is inaccessible (permission denied on a parent directory); a component of the path is a file, not a directory; the path is too long or contains invalid characters; underlying OS stat errors (e.g. I/O error, network mount down).
Common situations: ASDF_DATA_DIR pointing at an unavailable NFS/SMB mount; root-owned ~/.asdf making stat of children fail for the user; corrupted data dir where the plugin path's parent is a regular file; sandboxed CI denying filesystem access.
Related errors
- unable to create download dir: %w
- unable to create install dir: %w
- unable to create file plugin index touch file: %w
- unable to check if plugin exists: %w
- unable to create download dir: %w
AI-assisted analysis of asdf-vm/asdf@074a1722ca (2026-08-30).
Data as JSON: /api/errors/205ead2721761748.
Report an issue: GitHub.