{"record":{"id":"b904f50a437d42d1","repo":"lima-vm/lima","slug":"field-mounts-d-location-refers-to-a-non-direct","errorCode":null,"errorMessage":"field `mounts[%d].location` refers to a non-directory path: %#q: %w","messagePattern":"field `mounts\\[(.+?)\\]\\.location` refers to a non-directory path: %#q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/limayaml/validate.go","lineNumber":143,"sourceCode":"\t\tif !filepath.IsAbs(f.Location) && !strings.HasPrefix(f.Location, \"~\") {\n\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `mounts[%d].location` must be an absolute path, got %#q\",\n\t\t\t\ti, f.Location))\n\t\t}\n\t\t// f.Location has already been expanded in FillDefaults(), but that function cannot return errors.\n\t\tloc, err := localpathutil.Expand(f.Location)\n\t\tif err != nil {\n\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `mounts[%d].location` refers to an unexpandable path: %#q: %w\", i, f.Location, err))\n\t\t}\n\t\tst, err := os.Stat(loc)\n\t\tif err != nil {\n\t\t\tif !errors.Is(err, os.ErrNotExist) {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `mounts[%d].location` refers to an inaccessible path: %#q: %w\", i, f.Location, err))\n\t\t\t}\n\t\t\tif warn {\n\t\t\t\tlogrus.Warnf(\"field `mounts[%d].location` refers to a non-existent directory: %#q:\", i, f.Location)\n\t\t\t}\n\t\t} else if !st.IsDir() {\n\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `mounts[%d].location` refers to a non-directory path: %#q: %w\", i, f.Location, err))\n\t\t}\n\n\t\tswitch *f.MountPoint {\n\t\tcase \"/\", \"/bin\", \"/dev\", \"/etc\", \"/home\", \"/opt\", \"/sbin\", \"/tmp\", \"/usr\", \"/var\":\n\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `mounts[%d].mountPoint` must not be a system path such as /etc or /usr\", i))\n\t\t// home directory defined in \"cidata.iso:/user-data\"\n\t\tcase *y.User.Home:\n\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `mounts[%d].mountPoint` is the reserved internal home directory %#q\", i, *y.User.Home))\n\t\t}\n\t\t// There is no tilde-expansion for guest filenames\n\t\tif strings.HasPrefix(*f.MountPoint, \"~\") {\n\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `mounts[%d].mountPoint` must not start with `~`\", i))\n\t\t}\n\n\t\tif _, err := units.RAMInBytes(*f.NineP.Msize); err != nil {\n\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `msize` has an invalid value: %w\", err))\n\t\t}\n\t}","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/limayaml/validate.go#L125-L161","documentation":"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.)","triggerScenarios":"`mounts[i].location` points to a regular file (or other non-directory) that exists and is readable, during Validate.","commonSituations":"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.","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"],"exampleFix":"// before\nmounts:\n  - location: /home/me/config.yaml\n// after\nmounts:\n  - location: /home/me","handlingStrategy":"validation","validationCode":"const fs = require('fs'), os = require('os')\nfunction isMountableDir(loc) {\n  const p = loc.startsWith('~') ? require('path').join(os.homedir(), loc.slice(1)) : loc\n  try { return fs.statSync(p).isDirectory() } catch { return false }\n}","typeGuard":null,"tryCatchPattern":"try { await limactl(['template','validate', file]) } catch (e) { if (/non-directory path/.test(e.message)) { mountParentDirInstead(); } else throw e }","preventionTips":["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"],"tags":["lima","config-validation","mounts","filesystem"],"backgroundTag":"not-a-directory","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}