lima-vm/lima · error
field `mounts[%d].location` refers to a non-directory path:
Error message
field `mounts[%d].location` refers to a non-directory path: %#q: %w
What it means
If os.Stat succeeded but the target is not a directory, Validate() rejects the mount because only directories can be shared into the guest. (Note: the non-nil `err` in this branch is the earlier Stat result being nil, so %w typically renders nothing extra.)
Source
Thrown at pkg/limayaml/validate.go:143
if !filepath.IsAbs(f.Location) && !strings.HasPrefix(f.Location, "~") {
errs = errors.Join(errs, fmt.Errorf("field `mounts[%d].location` must be an absolute path, got %#q",
i, f.Location))
}
// f.Location has already been expanded in FillDefaults(), but that function cannot return errors.
loc, err := localpathutil.Expand(f.Location)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("field `mounts[%d].location` refers to an unexpandable path: %#q: %w", i, f.Location, err))
}
st, err := os.Stat(loc)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
errs = errors.Join(errs, fmt.Errorf("field `mounts[%d].location` refers to an inaccessible path: %#q: %w", i, f.Location, err))
}
if warn {
logrus.Warnf("field `mounts[%d].location` refers to a non-existent directory: %#q:", i, f.Location)
}
} else if !st.IsDir() {
errs = errors.Join(errs, fmt.Errorf("field `mounts[%d].location` refers to a non-directory path: %#q: %w", i, f.Location, err))
}
switch *f.MountPoint {
case "/", "/bin", "/dev", "/etc", "/home", "/opt", "/sbin", "/tmp", "/usr", "/var":
errs = errors.Join(errs, fmt.Errorf("field `mounts[%d].mountPoint` must not be a system path such as /etc or /usr", i))
// home directory defined in "cidata.iso:/user-data"
case *y.User.Home:
errs = errors.Join(errs, fmt.Errorf("field `mounts[%d].mountPoint` is the reserved internal home directory %#q", i, *y.User.Home))
}
// There is no tilde-expansion for guest filenames
if strings.HasPrefix(*f.MountPoint, "~") {
errs = errors.Join(errs, fmt.Errorf("field `mounts[%d].mountPoint` must not start with `~`", i))
}
if _, err := units.RAMInBytes(*f.NineP.Msize); err != nil {
errs = errors.Join(errs, fmt.Errorf("field `msize` has an invalid value: %w", err))
}
}View on GitHub (pinned to dd909d0973)
Solutions
- Change the location to the containing directory of the intended file
- If a single file must be available, mount its parent directory instead
- Verify with `ls -ld <location>` that it is a directory
Example fix
// before mounts: - location: /home/me/config.yaml // after mounts: - location: /home/me
Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs'), os = require('os')
function isMountableDir(loc) {
const p = loc.startsWith('~') ? require('path').join(os.homedir(), loc.slice(1)) : loc
try { return fs.statSync(p).isDirectory() } catch { return false }
} Try / catch
try { await limactl(['template','validate', file]) } catch (e) { if (/non-directory path/.test(e.message)) { mountParentDirInstead(); } else throw e } Prevention
- Run `ls -ld` on each mount location before adding it
- Remember only directories are mountable; share files via their parent dir
- Watch for symlinks whose targets changed to files
When it happens
Trigger: `mounts[i].location` points to a regular file (or other non-directory) that exists and is readable, during Validate.
Common situations: Typing the path to a file instead of its containing directory; a symlink whose target was replaced by a file; mounting a socket/device path by mistake.
Related errors
- field `mounts[%d].location` must be an absolute path, got %#
- field `mounts[%d].location` refers to an unexpandable path:
- field `mounts[%d].location` refers to an inaccessible path:
- field `mounts[%d].mountPoint` must not be a system path such
- field `mounts[%d].mountPoint` is the reserved internal home
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/b904f50a437d42d1.
Report an issue: GitHub.