asdf-vm/asdf · error
unable to create download dir: %w
Error message
unable to create download dir: %w
What it means
InstallOneVersion creates a per-install download directory (conf.DataDir/downloads/<plugin>/<version>) and exports it as ASDF_DOWNLOAD_PATH before running download hooks/callbacks. If os.MkdirAll fails — permissions, disk full, path is a file — installation aborts with this wrapped error before anything is downloaded.
Source
Thrown at internal/versions/versions.go:174
downloadDir := installs.DownloadPath(conf, plugin, version)
installDir := installs.InstallPath(conf, plugin, version)
if installs.IsInstalled(conf, plugin, version) {
return VersionAlreadyInstalledError{version: version, toolName: plugin.Name}
}
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)View on GitHub (pinned to 074a1722ca)
Solutions
- Check disk space (df -h) and free space if full
- Fix ownership/permissions on ASDF_DATA_DIR and its downloads/ tree
- Ensure ASDF_DATA_DIR is on a writable mount
- Remove any non-directory file occupying the download path
Defensive patterns
Strategy: validation
Validate before calling
if err := os.MkdirAll(downloadDir, 0o777); err != nil {
return fmt.Errorf("download dir not writable: %w", err)
}
if free, err := diskFree(dataDir); err == nil && free < minNeeded {
return fmt.Errorf("insufficient disk space")
} Try / catch
if err != nil && strings.Contains(err.Error(), "unable to create download dir") {
// check disk space / permissions, then retry install
} Prevention
- Monitor disk space on the ASDF_DATA_DIR volume
- Keep ASDF_DATA_DIR owned by the running user
- Don't place files where asdf expects download directories
When it happens
Trigger: os.MkdirAll(downloadDir, 0o777) returns an error: parent dirs unwritable, ASDF_DATA_DIR on a read-only mount, disk full, or a non-directory already exists at the download path.
Common situations: Read-only or full filesystem, running asdf as a different user than the data dir owner, ASDF_DATA_DIR pointing at a restricted path, leftover file where the downloads dir should be.
Related errors
- unable to create download dir: %w
- unable to create install dir: %w
- unable to create file plugin index touch file: %w
- unable to check if plugin already exists: %w
- unable to check if plugin exists: %w
AI-assisted analysis of asdf-vm/asdf@074a1722ca (2026-08-30).
Data as JSON: /api/errors/c08938893241c0fa.
Report an issue: GitHub.