{"record":{"id":"205ead2721761748","repo":"asdf-vm/asdf","slug":"unable-to-check-if-plugin-already-exists-w","errorCode":null,"errorMessage":"unable to check if plugin already exists: %w","messagePattern":"unable to check if plugin already exists: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/plugins/plugins.go","lineNumber":369,"sourceCode":"\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\treturn plugins, nil\n}\n\n// Add takes plugin name and Git URL and installs the plugin if it isn't\n// already installed\nfunc Add(config config.Config, pluginName, pluginURL, ref string) error {\n\terr := validatePluginName(pluginName)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\texists, err := PluginExists(config.DataDir, pluginName)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to check if plugin already exists: %w\", err)\n\t}\n\n\tif exists {\n\t\treturn NewPluginAlreadyExists(pluginName)\n\t}\n\n\tplugin := New(config, pluginName)\n\n\tif pluginURL == \"\" {\n\t\t// Ignore error here as the default value is fine\n\t\tdisablePluginIndex, _ := config.DisablePluginShortNameRepository()\n\n\t\tif disablePluginIndex {\n\t\t\treturn fmt.Errorf(\"Short-name plugin repository is disabled\")\n\t\t}\n\n\t\tlastCheckDuration := 0\n\t\t// We don't care about errors here as we can use the default value","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/asdf-vm/asdf/blob/074a1722ca88d6677f228541ce06efaf4f9924d4/internal/plugins/plugins.go#L351-L387","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: parent path is a file\n~/.asdf/plugins exists as a regular file\n# Error: unable to check if plugin already exists: ...\n// after\nrm \"$HOME/.asdf/plugins\"   # remove the offending file\nmkdir -p \"$HOME/.asdf/plugins\"","handlingStrategy":"validation","validationCode":"dataDir := conf.DataDir\nif fi, err := os.Stat(dataDir); err != nil || !fi.IsDir() {\n    if err := os.MkdirAll(dataDir, 0o755); err != nil {\n        return fmt.Errorf(\"data dir unusable: %w\", err)\n    }\n}\n// probe writability of plugins path before Add\nprobe := filepath.Join(dataDir, \"plugins\", \".probe\")\nos.MkdirAll(filepath.Dir(probe), 0o755)\nif err := os.WriteFile(probe, nil, 0o644); err != nil {\n    return err\n}\nos.Remove(probe)","typeGuard":null,"tryCatchPattern":"if err := plugins.Add(conf, pluginName, repoURL); err != nil {\n    if strings.Contains(err.Error(), \"unable to check if plugin already exists\") {\n        log.Printf(\"fix data dir access (%s): %v\", conf.DataDir, err)\n    }\n}","preventionTips":["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."],"tags":["filesystem","permissions","plugin"],"backgroundTag":"plugin-exists-check-failed","analyzedSha":"074a1722ca88d6677f228541ce06efaf4f9924d4","analyzedAt":"2026-08-30T19:56:42.972Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}