asdf-vm/asdf · error

unable to update plugin index: %w

Error message

unable to update plugin index: %w

What it means

doUpdate refreshes an existing plugin index repository with p.repo.Update("") (fetch to latest commit). If the git update fails, the error is wrapped as 'unable to update plugin index'. This path only runs when the index already exists but is older than the staleness threshold.

Source

Thrown at internal/pluginindex/pluginindex.go:109

		return p.doUpdate()
	}

	// Convert minutes to nanoseconds
	updateDurationNs := int64(p.updateDurationMinutes) * (6e10)

	if updated > updateDurationNs && !p.disableUpdate {
		return p.doUpdate()
	}

	return false, nil
}

func (p PluginIndex) doUpdate() (bool, error) {
	// pass in empty string as we want the repo to figure out what the latest
	// commit is
	_, _, _, err := p.repo.Update("")
	if err != nil {
		return false, fmt.Errorf("unable to update plugin index: %w", err)
	}

	// Touch update file
	return touchFS(p.directory)
}

// GetPluginSourceURL looks up a plugin by name and returns the repository URL
// for easy install by the user.
func (p PluginIndex) GetPluginSourceURL(name string) (string, error) {
	_, err := p.Refresh()
	if err != nil {
		return "", err
	}

	url, err := readPlugin(p.directory, name)
	if err != nil {
		return "", err
	}

View on GitHub (pinned to 074a1722ca)

Solutions

  1. Check network access to the index remote and retry — updates are transient failures.
  2. Delete the index directory (default ~/.asdf/repository or repo/ under the index dir) and let Refresh re-clone it.
  3. Fix the local clone manually (git -C <dir> fetch && git reset --hard origin).
  4. Verify git/proxy configuration if behind a firewall.

Example fix

// before: corrupt/stale index repo
// after: re-clone from scratch
rm -rf "${ASDF_DATA_DIR:-$HOME/.asdf}/repository"
asdf plugin list all   # triggers fresh clone
Defensive patterns

Strategy: fallback

Validate before calling

if fi, err := os.Stat(filepath.Join(indexDir, ".git")); err != nil || !fi.IsDir() {
    // repo missing/corrupt — remove so Refresh re-clones
    os.RemoveAll(indexDir)
}

Try / catch

ok, err := idx.Refresh()
if err != nil && strings.Contains(err.Error(), "unable to update plugin index") {
    os.RemoveAll(indexDir)      // nuke broken clone
    ok, err = idx.Refresh()     // fresh clone fallback
}

Prevention

When it happens

Trigger: Refresh (via Get/GetPluginSourceURL) when the index repo exists and the update-timestamp is stale, and: the network is down; the remote rejected the fetch (auth, rate limit); the local clone has diverged or is corrupt; git is unavailable.

Common situations: Intermittent network drops; GitHub outages or rate limiting; local index repo left in a dirty/broken state by a killed process; VPN disconnected.

Related errors


AI-assisted analysis of asdf-vm/asdf@074a1722ca (2026-08-30). Data as JSON: /api/errors/b30bb822f2cf983c. Report an issue: GitHub.