asdf-vm/asdf · error

failed to run pre-install hook: %w

Error message

failed to run pre-install hook: %w

What it means

After download, InstallOneVersion runs the pre_asdf_install hook via hook.RunWithOutput; failure of this user-configured hook aborts the install with this wrapped error, before the install directory is created and the plugin's install callback runs. Like error 47 but at the install stage rather than the download stage.

Source

Thrown at internal/versions/versions.go:189

	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)
	if err != nil {
		if rmErr := os.RemoveAll(installDir); rmErr != nil {
			fmt.Fprintf(stdErr, "failed to clean up '%s' due to %s\n", installDir, rmErr)
		}
		return fmt.Errorf("failed to run install callback: %w", err)
	}

	// Reshim
	err = shims.GenerateAll(conf, stdOut, stdErr)
	if err != nil {

View on GitHub (pinned to 074a1722ca)

Solutions

  1. Read the hook's output on stdOut/stdErr to see the real reason
  2. Fix or remove the pre_asdf_install hook in asdf config
  3. Ensure the hook command is present and executable in PATH
  4. Choose a version that satisfies the hook's policy if it is intentionally blocking
Defensive patterns

Strategy: try-catch

Validate before calling

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

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to run pre-install hook") {
    // inspect hook output, fix hook or pick another version
}

Prevention

When it happens

Trigger: hook.RunWithOutput(conf, "pre_asdf_install_<plugin>", [version], ...) returns an error — a configured pre_asdf_install or pre_asdf_install_<plugin> hook exits non-zero or fails to execute.

Common situations: Pre-install hooks enforcing policies (approved versions, disk checks) that reject the version, hook scripts broken or missing, environment differences for the user running the install.

Related errors


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