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
- Check permissions on the install path parent and chown/chmod so the current user can write.
- Verify ASDF_DATA_DIR (or default ~/.asdf) points to a writable location.
- Remove any regular file occupying the installDir path.
- 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
- Run mkdir -p on the data dir during environment setup and chown it to the running user.
- Keep ASDF_DATA_DIR on local writable storage, not read-only mounts.
- Check free disk space before large installs in CI.
- Never let a file occupy a directory path under the asdf data dir.
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
- unable to create download dir: %w
- unable to create download 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/f56b83784a519889.
Report an issue: GitHub.