{"record":{"id":"f38a4960561b6de6","repo":"asdf-vm/asdf","slug":"error-fetching-plugin-url-s","errorCode":null,"errorMessage":"error fetching plugin URL: %s","messagePattern":"error fetching plugin URL: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/plugins/plugins.go","lineNumber":398,"sourceCode":"\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\n\t\tcheckDuration, _ := config.PluginRepositoryLastCheckDuration()\n\n\t\tif !checkDuration.Never {\n\t\t\tlastCheckDuration = checkDuration.Every\n\t\t}\n\n\t\tindex := pluginindex.Build(config.DataDir, config.PluginIndexURL, false, lastCheckDuration)\n\t\tvar err error\n\t\tpluginURL, err = index.GetPluginSourceURL(pluginName)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error fetching plugin URL: %s\", err)\n\t\t}\n\t}\n\n\tplugin.URL = pluginURL\n\n\t// Run pre hooks\n\thook.Run(config, \"pre_asdf_plugin_add\", []string{plugin.Name})\n\thook.Run(config, fmt.Sprintf(\"pre_asdf_plugin_add_%s\", plugin.Name), []string{})\n\n\terr = git.NewRepo(plugin.Dir).Clone(plugin.URL, ref)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = os.MkdirAll(data.DownloadDirectory(config.DataDir, plugin.Name), 0o777)\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/asdf-vm/asdf/blob/074a1722ca88d6677f228541ce06efaf4f9924d4/internal/plugins/plugins.go#L380-L416","documentation":"When Add is called with a short plugin name (no explicit URL), asdf looks the name up in the plugin index via pluginindex.Build(...).GetPluginSourceURL. If that lookup fails (name not in index, network/git failure fetching the index, or stale cached index), the error is wrapped as \"error fetching plugin URL\". The wrapped inner error tells you which of these happened.","triggerScenarios":"plugins.Add with empty pluginURL where GetPluginSourceURL returns an error: plugin name not present in the index, the plugin index repo failed to clone/update (network down, bad PluginIndexURL), or the cached index is unreadable.","commonSituations":"Typo'd plugin short name (`asdf plugin add nodejs-lts`), offline/air-gapped environment blocking the index git fetch, custom ASDF_PLUGIN_INDEX_URL (config.PluginIndexURL) pointing at a missing or private repo.","solutions":["Verify the exact plugin name exists in the plugin index (https://github.com/asdf-vm/asdf-plugins); fix typos","Add the plugin with an explicit git URL instead of a short name to skip the index lookup entirely","Check network/proxy access to the index git repository; test with `git ls-remote <index-url>`","Inspect the wrapped error text — if it mentions git clone, fix the PluginIndexURL or clear the stale index cache under config.DataDir"],"exampleFix":"// before\nerr := plugins.Add(conf, \"nodjs\", \"\", \"\", os.Stdout) // typo -> index lookup fails\n// after\nerr := plugins.Add(conf, \"nodejs\", \"https://github.com/asdf-vm/asdf-nodejs.git\", \"\", os.Stdout)","handlingStrategy":"fallback","validationCode":"// verify name is known in index before Add:\nurl, err := index.GetPluginSourceURL(name)\nif err != nil { url = \"https://github.com/asdf-vm/asdf-\" + name } // or error out","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var inner error = errors.Unwrap(err)\n    // inspect inner: git failure vs name-not-found, then retry with explicit URL\n}","preventionTips":["Prefer explicit plugin URLs over short names in scripts","Check index/network reachability (git ls-remote) in CI before installs"],"tags":["network","plugin-index","git"],"backgroundTag":"plugin-not-in-index","analyzedSha":"074a1722ca88d6677f228541ce06efaf4f9924d4","analyzedAt":"2026-08-30T19:56:42.972Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}