lima-vm/lima · error
could not create %#q directory: %w
Error message
could not create %#q directory: %w
What it means
DefaultPubKeys ensures $LIMA_HOME/_config exists before generating a default key pair; if os.MkdirAll of that directory fails the error is wrapped with the directory path. This usually indicates a filesystem-level problem, not a Lima logic error.
Source
Thrown at pkg/sshutil/sshutil.go:305
// DefaultPubKeys returns the public key from $LIMA_HOME/_config/user.pub.
// The key will be created if it does not yet exist.
//
// When loadDotSSH is true, ~/.ssh/*.pub will be appended to make the VM accessible without specifying
// an identity explicitly.
func DefaultPubKeys(ctx context.Context, loadDotSSH bool) ([]PubKey, error) {
// Read $LIMA_HOME/_config/user.pub
configDir, err := dirnames.LimaConfigDir()
if err != nil {
return nil, err
}
_, err = os.Stat(filepath.Join(configDir, filenames.UserPrivateKey))
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return nil, err
}
if err := os.MkdirAll(configDir, 0o700); err != nil {
return nil, fmt.Errorf("could not create %#q directory: %w", configDir, err)
}
if err := lockutil.WithDirLock(configDir, func() error {
// no passphrase, no user@host comment
privPath := filepath.Join(configDir, filenames.UserPrivateKey)
keygenExe := "ssh-keygen"
if runtime.GOOS == "windows" {
sshExe, sshErr := NewSSHExe()
if sshErr != nil {
return sshErr
}
keygenExe = companionForSSH(sshExe, "ssh-keygen")
privPath, err = PathForSSH(ctx, sshExe, privPath)
if err != nil {
return err
}
}
keygenCmd := exec.CommandContext(ctx, keygenExe, "-t", "ed25519", "-q", "-N", "",
"-C", "lima", "-f", privPath)View on GitHub (pinned to dd909d0973)
Solutions
- Verify $LIMA_HOME (default ~/.lima) is writable by the current user; create it manually with mkdir -p ~/.lima/_config and chmod 700.
- If a regular file named _config exists, remove or rename it.
- Check the wrapped OS error in the message for the concrete cause (EACCES, ENOSPC, ENOTDIR).
Example fix
// before export LIMA_HOME=/mnt/readonly/lima limactl create // after export LIMA_HOME=$HOME/.lima mkdir -p "$LIMA_HOME/_config" && chmod 700 "$LIMA_HOME/_config" limactl create
Defensive patterns
Strategy: validation
Validate before calling
configDir := filepath.Join(limaHome, "_config")
if info, err := os.Stat(configDir); err == nil && !info.IsDir() {
return fmt.Errorf("%s exists but is not a directory", configDir)
}
if err := os.MkdirAll(configDir, 0o700); err != nil { return err } Type guard
func writableDir(p string) bool { return os.MkdirAll(p, 0o700) == nil } Try / catch
keys, err := sshutil.DefaultPubKeys(ctx)
if err != nil {
if strings.Contains(err.Error(), "could not create") {
// check LIMA_HOME writability and report to user
}
return err
} Prevention
- Verify LIMA_HOME points to a writable, local directory
- Ensure nothing named _config exists as a regular file
- Check disk space before instance creation
When it happens
Trigger: Calling DefaultPubKeys (directly or via templateArgs) when _config does not exist yet and MkdirAll fails: read-only $LIMA_HOME, permission denied on the parent, disk full, or the path exists as a non-directory (a file named _config).
Common situations: LIMA_HOME pointing at a read-only or non-writable location; a stale file where the _config directory should be; running under a user without write access to the home dir; NFS/Windows mount quirks.
Related errors
- failed to unprotect instance %#q: %w
- open disk: %w
- failed to remove the autostart entry for instance %#q: %w
- failed to remove stale raw image %q: %w
- failed to remove stale raw digest file %q: %w
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/442e41f84e306316.
Report an issue: GitHub.