asdf-vm/asdf · error

unable to create install dir: %w

Error message

unable to create install dir: %w

What it means

After running the download callback, InstallOneVersion creates the final install directory with os.MkdirAll(installDir, 0o777). If that filesystem operation fails, the error is wrapped as 'unable to create install dir'. This is an OS-level permission or path problem, not a plugin problem.

Source

Thrown at internal/installtest/installtest.go:56

		"ASDF_INSTALL_VERSION": version,
		"ASDF_INSTALL_PATH":    installDir,
		"ASDF_DOWNLOAD_PATH":   downloadDir,
		"ASDF_CONCURRENCY":     "1",
	}

	err = os.MkdirAll(downloadDir, 0o777)
	if err != nil {
		return fmt.Errorf("unable to create download dir: %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 = 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 {
		return fmt.Errorf("failed to run install callback: %w", err)
	}

	return nil
}

// InstallPath returns the path to a tool installation
func InstallPath(conf config.Config, plugin plugins.Plugin, version string) string {
	return filepath.Join(pluginInstallPath(conf, plugin), formatVersionStringForFS(version))
}

// DownloadPath returns the download path for a particular plugin and version
func DownloadPath(conf config.Config, plugin plugins.Plugin, version string) string {
	return filepath.Join(conf.DataDir, dataDirDownloads, plugin.Name, formatVersionStringForFS(version))

View on GitHub (pinned to 074a1722ca)

Solutions

  1. Check permissions on the install path parent and chown/chmod so the current user can write.
  2. Verify ASDF_DATA_DIR (or default ~/.asdf) points to a writable location.
  3. Remove any regular file occupying the installDir path.
  4. Free disk space or remount the filesystem read-write.

Example fix

// before: data dir not writable
export ASDF_DATA_DIR=/opt/asdf   # root-owned
// after
export ASDF_DATA_DIR="$HOME/.asdf"
mkdir -p "$ASDF_DATA_DIR"
Defensive patterns

Strategy: validation

Validate before calling

if err := os.MkdirAll(installDir, 0o777); err != nil {
    return fmt.Errorf("precheck install dir: %w", err)
}
if fi, err := os.Stat(filepath.Dir(installDir)); err == nil && !fi.IsDir() {
    return fmt.Errorf("%s is not a directory", filepath.Dir(installDir))
}

Try / catch

if err := installtest.InstallOneVersion(conf, plugin, version); err != nil {
    if strings.Contains(err.Error(), "unable to create install dir") {
        log.Printf("check ASDF_DATA_DIR writability: %v", err)
    }
}

Prevention

When it happens

Trigger: Calling InstallOneVersion when: the parent of installDir does not exist and cannot be created; the process lacks write permission on the path; installDir exists as a regular file; the filesystem is read-only or full; the path contains invalid components.

Common situations: ASDF_DATA_DIR pointed at a root-owned or read-only location; HOME unset or not writable in CI containers; disk quota exceeded; a stray file occupying the plugin install path after a corrupted prior install.

Related errors


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