{"record":{"id":"cf1879423b31eb12","repo":"lima-vm/lima","slug":"failed-to-unmount-q-w-output-q","errorCode":null,"errorMessage":"failed to unmount %#q: %w (output=%#q)","messagePattern":"failed to unmount %#q: %w \\(output=%#q\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/osutil/mount_darwin.go","lineNumber":35,"sourceCode":"func Mount(ctx context.Context, fs, dev, mnt string, options []string) error {\n\targs := []string{\"-t\", fs}\n\tif len(options) > 0 {\n\t\targs = append(args, \"-o\", strings.Join(options, \",\"))\n\t}\n\targs = append(args, dev, mnt)\n\tcmd := exec.CommandContext(ctx, \"mount\", args...)\n\tlogrus.Debugf(\"Executing command: %v\", cmd.Args)\n\tif output, err := cmd.CombinedOutput(); err != nil {\n\t\treturn fmt.Errorf(\"failed to mount %#q on %#q: %w (output=%#q)\", dev, mnt, err, output)\n\t}\n\treturn nil\n}\n\nfunc Umount(ctx context.Context, mnt string) error {\n\tcmd := exec.CommandContext(ctx, \"umount\", mnt)\n\tlogrus.Debugf(\"Executing command: %v\", cmd.Args)\n\tif output, err := cmd.CombinedOutput(); err != nil {\n\t\treturn fmt.Errorf(\"failed to unmount %#q: %w (output=%#q)\", mnt, err, output)\n\t}\n\treturn nil\n}\n","sourceCodeStart":17,"sourceCodeEnd":39,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/osutil/mount_darwin.go#L17-L39","documentation":"Umount() on macOS runs the external `umount <mnt>` command and, on non-zero exit, returns this error wrapping the exit error plus the command's combined output. It signals that the kernel/refused unmount of the given path.","triggerScenarios":"Umount is called on a path that is still busy (open files, running processes), not a mount point, or requires privileges and lacks them; the umount subprocess exits non-zero.","commonSituations":"Tearing down a Lima instance while a VM process still holds the mount; unmounting an already-unmounted path; resource busy during shutdown sequencing.","solutions":["Read the `output=` field — umount reports 'busy' vs 'not currently mounted' distinctly.","For busy mounts, find and stop processes using it (lsof +f -- <mnt> or diskutil unmount force).","Ignore 'not mounted' errors as idempotent cleanup if appropriate.","Retry after the consumer (VM) has fully exited."],"exampleFix":"// before: umount while guestagent still running -> busy\n// after: stop VM first, then umount with retry\nif err := osutil.Umount(ctx, mnt); err != nil && !strings.Contains(err.Error(), \"not currently mounted\") { return err }","handlingStrategy":"retry","validationCode":"// only attempt umount if it is actually a mount point\nout, _ := exec.Command(\"mount\").Output()\nif !bytes.Contains(out, []byte(mnt)) {\n    return nil // already unmounted; skip\n}","typeGuard":null,"tryCatchPattern":"err := osutil.Umount(ctx, mnt)\nif err != nil && strings.Contains(err.Error(), \"busy\") {\n    time.Sleep(500 * time.Millisecond)\n    err = osutil.Umount(ctx, mnt) // retry after consumers exit\n}","preventionTips":["Fully stop the VM/consumer before unmounting","Treat 'not currently mounted' as success for idempotent cleanup","Use lsof to verify no process holds the mount before teardown"],"tags":["macos","umount","filesystem","subprocess"],"backgroundTag":"mount-command-failed","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}