asdf-vm/asdf · error

failed to run pre-download hook: %w

Error message

failed to run pre-download hook: %w

What it means

Before downloading, InstallOneVersion runs the pre_asdf_download hook via hook.RunWithOutput, which executes user-configured hook commands (from asdf config, e.g. pre_asdf_download_nodejs) and surfaces their failure. A non-zero hook exit is wrapped as 'failed to run pre-download hook', aborting the install before the plugin's download callback runs.

Source

Thrown at internal/versions/versions.go:179

	}

	concurrency, _ := conf.Concurrency()
	env := map[string]string{
		"ASDF_INSTALL_TYPE":    version.Type,
		"ASDF_INSTALL_VERSION": version.Value,
		"ASDF_INSTALL_PATH":    installDir,
		"ASDF_DOWNLOAD_PATH":   downloadDir,
		"ASDF_CONCURRENCY":     concurrency,
	}

	err = os.MkdirAll(downloadDir, 0o777)
	if err != nil {
		return fmt.Errorf("unable to create download dir: %w", err)
	}

	err = hook.RunWithOutput(conf, fmt.Sprintf("pre_asdf_download_%s", plugin.Name), []string{version.Value}, stdOut, stdErr)
	if err != nil {
		return fmt.Errorf("failed to run pre-download hook: %w", err)
	}

	err = plugin.RunCallback("download", []string{}, env, stdOut, stdErr)
	if _, ok := err.(plugins.NoCallbackError); err != nil && !ok {
		return fmt.Errorf("failed to run download callback: %w", err)
	}

	err = hook.RunWithOutput(conf, fmt.Sprintf("pre_asdf_install_%s", plugin.Name), []string{version.Value}, stdOut, stdErr)
	if err != nil {
		return fmt.Errorf("failed to run pre-install hook: %w", err)
	}

	err = os.MkdirAll(installDir, 0o777)
	if err != nil {
		return fmt.Errorf("unable to create install dir: %w", err)
	}

	err = plugin.RunCallback("install", []string{}, env, stdOut, stdErr)

View on GitHub (pinned to 074a1722ca)

Solutions

  1. Look at the hook's own output on stdOut/stdErr for the real failure
  2. Inspect the pre_asdf_download hook definition in asdf config and fix or remove it
  3. Ensure the hook command exists in PATH and is executable
  4. Retry the install after the hook's blocking condition (e.g. approval, network policy) is resolved

Example fix

// before (in asdf config)
pre_asdf_download = /usr/local/bin/check-license $version  # exits 1
// after
pre_asdf_download = /usr/local/bin/check-license $version || true
Defensive patterns

Strategy: try-catch

Validate before calling

// test hooks beforehand:
if err := hook.RunWithOutput(conf, "pre_asdf_download_"+plugin, []string{ver}, buf, buf); err != nil {
    return fmt.Errorf("pre-download hook will fail: %w", err)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to run pre-download hook") {
    // inspect hook output, fix or bypass hook, retry
}

Prevention

When it happens

Trigger: hook.RunWithOutput(conf, "pre_asdf_download_<plugin>", [version], ...) returns an error — a configured pre_asdf_download or pre_asdf_download_<plugin> hook exits non-zero or cannot be executed.

Common situations: Corporate pre-download hooks doing license/security checks that fail, hook commands missing from PATH, or hooks failing on a particular tool version.

Related errors


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