{"record":{"id":"51e6c1863fc2fa7e","repo":"lima-vm/lima","slug":"unexpected-symlink-target-for-virtiofs-mount-sourc","errorCode":null,"errorMessage":"unexpected symlink target for virtiofs mount source %#q: expected %#q, got %#q","messagePattern":"unexpected symlink target for virtiofs mount source %#q: expected %#q, got %#q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/guestagent/fakecloudinit/fakecloudinit_darwin.go","lineNumber":176,"sourceCode":"\n// mountVirtiofs symlinks `/Volumes/My Shared Files/<pseudoTag>` (automatically mounted by macOS) to dir.\n// dir must not exist, or, must be a symlink to the expected source.\nfunc mountVirtiofs(pseudoTag, dir string) error {\n\tif strings.Contains(pseudoTag, string(filepath.Separator)) {\n\t\treturn fmt.Errorf(\"invalid pseudo tag for virtiofs: %#q\", pseudoTag)\n\t}\n\tlnSrc := filepath.Join(\"/Volumes/My Shared Files\", pseudoTag)\n\n\t// FIXME: verify that the filesystem of lnSrc is indeed read-only when user-data contains the \"ro\" option.\n\t// unix.Statfs() could be used, but unix.Statfs_t.Flags & unix.MNT_RDONLY seems always 0 for virtiofs.\n\t// `mount -v` does not show \"ro\" flag either.\n\n\tlnExisting, err := os.Readlink(dir)\n\tif err == nil {\n\t\tif lnExisting == lnSrc {\n\t\t\treturn nil // already symlinked\n\t\t}\n\t\treturn fmt.Errorf(\"unexpected symlink target for virtiofs mount source %#q: expected %#q, got %#q\", lnSrc, lnSrc, lnExisting)\n\t}\n\tif !errors.Is(err, os.ErrNotExist) {\n\t\tlogrus.WithError(err).Warnf(\"Failed to read existing symlink for virtiofs mount source %#q\", lnSrc)\n\t}\n\tif err := os.Symlink(lnSrc, dir); err != nil {\n\t\treturn fmt.Errorf(\"failed to create symlink from %#q to %#q: %w\", lnSrc, dir, err)\n\t}\n\treturn nil\n}\n\nfunc setTimezone(ctx context.Context, timezone string) error {\n\tcmd := exec.CommandContext(ctx, \"systemsetup\", \"-settimezone\", timezone)\n\tlogrus.Infof(\"Executing command: %v\", cmd.Args)\n\tif output, err := cmd.CombinedOutput(); err != nil {\n\t\treturn fmt.Errorf(\"failed to execute command %v: %w (output=%#q)\", cmd.Args, err, output)\n\t}\n\treturn nil\n}","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/guestagent/fakecloudinit/fakecloudinit_darwin.go#L158-L194","documentation":"Raised by mountVirtiofs when the destination directory already exists as a symlink but points to a different target than the expected /Volumes/My Shared Files/<pseudoTag> location. The agent refuses to silently repoint an existing symlink it did not create, reporting expected vs got targets.","triggerScenarios":"os.Readlink(dir) succeeds but the existing link target differs from lnSrc - e.g. a previous boot used a different pseudo tag, the user manually created the symlink, or the destination was reused from an older instance configuration.","commonSituations":"Changing the Lima mount tag for the same guest destination path, pointing two different mounts at the same destination, or leftover symlinks from an earlier VM created on the same disk image.","solutions":["Read the `got` target in the message to identify what currently occupies the path.","Delete or update the stale symlink in the guest (e.g. `sudo rm /mnt/share` in the VM) so the next boot can recreate it correctly.","Make sure the same destination path is not used by multiple mounts entries with different sources.","If the existing target is actually correct, align the user-data pseudo tag with it instead of the other way around."],"exampleFix":"// inside guest VM\n// before\n$ ls -l /mnt/share  # -> /Volumes/My Shared Files/OldTag\n$ sudo rm /mnt/share\n// after (let fakecloudinit recreate it)\n$ ls -l /mnt/share  # -> /Volumes/My Shared Files/ExpectedTag","handlingStrategy":"validation","validationCode":"func checkSymlinkTarget(dir, expected string) error {\n  if existing, err := os.Readlink(dir); err == nil && existing != expected {\n    return fmt.Errorf(\"%s is a symlink to %s, expected %s - remove it before provisioning\", dir, existing, expected)\n  }\n  return nil\n}","typeGuard":"func isSymlinkTo(dir, expected string) bool {\n  existing, err := os.Readlink(dir)\n  return err == nil && existing == expected\n}","tryCatchPattern":"lnExisting, err := os.Readlink(dir)\nif err == nil && lnExisting != lnSrc {\n  // decide: repair or fail\n  if err := os.Remove(dir); err != nil { return fmt.Errorf(\"stale symlink %s: %w\", dir, err) }\n}","preventionTips":["Keep mount tags stable across instance recreations.","Do not reuse the same destination path for different mount sources.","Clean stale symlinks when regenerating a VM from the same disk image.","Document that the agent only accepts a matching or non-existent destination."],"tags":["macos","cloud-init","symlink","virtiofs","state-conflict"],"backgroundTag":"symlink-target-mismatch","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}