lima-vm/lima · error

invalid pseudo tag for virtiofs: %#q

Error message

invalid pseudo tag for virtiofs: %#q

What it means

Raised by mountVirtiofs when the virtiofs mount source (pseudo tag) contains a path separator. The pseudo tag is used verbatim as the last component of /Volumes/My Shared Files/<pseudoTag>, so it must be a plain name, not a path. The offending tag is printed in the message.

Source

Thrown at pkg/guestagent/fakecloudinit/fakecloudinit_darwin.go:163

// The entries are not written to /etc/fstab.
func mountFSTabEntry(m []string) error {
	if len(m) != 6 {
		return fmt.Errorf("invalid fstab entry: expected 6 fields, got %d: %v", len(m), m)
	}
	src, dst, fsType := m[0], m[1], m[2]
	switch fsType {
	case "virtiofs":
		return mountVirtiofs(src, dst)
	default:
		return fmt.Errorf("unsupported filesystem type %#q for fstab entry: %v", fsType, m)
	}
}

// mountVirtiofs symlinks `/Volumes/My Shared Files/<pseudoTag>` (automatically mounted by macOS) to dir.
// dir must not exist, or, must be a symlink to the expected source.
func mountVirtiofs(pseudoTag, dir string) error {
	if strings.Contains(pseudoTag, string(filepath.Separator)) {
		return fmt.Errorf("invalid pseudo tag for virtiofs: %#q", pseudoTag)
	}
	lnSrc := filepath.Join("/Volumes/My Shared Files", pseudoTag)

	// FIXME: verify that the filesystem of lnSrc is indeed read-only when user-data contains the "ro" option.
	// unix.Statfs() could be used, but unix.Statfs_t.Flags & unix.MNT_RDONLY seems always 0 for virtiofs.
	// `mount -v` does not show "ro" flag either.

	lnExisting, err := os.Readlink(dir)
	if err == nil {
		if lnExisting == lnSrc {
			return nil // already symlinked
		}
		return fmt.Errorf("unexpected symlink target for virtiofs mount source %#q: expected %#q, got %#q", lnSrc, lnSrc, lnExisting)
	}
	if !errors.Is(err, os.ErrNotExist) {
		logrus.WithError(err).Warnf("Failed to read existing symlink for virtiofs mount source %#q", lnSrc)
	}
	if err := os.Symlink(lnSrc, dir); err != nil {

View on GitHub (pinned to dd909d0973)

Solutions

  1. Replace the src field with the bare pseudo tag (single path component, no slashes) of the shared directory.
  2. Look up the correct tag: it is the name of the directory macOS auto-mounts under /Volumes/My Shared Files (e.g. via Lima's mount tags).
  3. If you need a subdirectory, create a symlink inside the guest pointing at the desired path rather than encoding it in the pseudo tag.
  4. Verify the share is actually configured in the Lima YAML mounts so /Volumes/My Shared Files/<tag> exists.

Example fix

// before (user-data)
mounts:
  - ["/Users/foo/share", "/mnt/share", "virtiofs", "ro", "0", "0"]
// after
mounts:
  - ["share", "/mnt/share", "virtiofs", "ro", "0", "0"]
Defensive patterns

Strategy: validation

Validate before calling

func validatePseudoTag(src string) error {
  if src == "" { return errors.New("pseudo tag is empty") }
  if strings.ContainsAny(src, "/\\") { return fmt.Errorf("pseudo tag %q must be a single path component", src) }
  return nil
}

Type guard

func isSinglePathComponent(s string) bool { return s != "" && !strings.Contains(s, string(filepath.Separator)) }

Try / catch

if err := mountFSTabEntry(m); err != nil {
  if strings.Contains(err.Error(), "invalid pseudo tag") {
    log.Warnf("fix mounts src %q to a bare share tag", m[0])
    continue
  }
  return err
}

Prevention

When it happens

Trigger: A mounts entry whose first field (src) contains a `/` (e.g. `/Users/foo/share` or `share/sub`), which would otherwise try to join outside the fixed /Volumes/My Shared Files directory.

Common situations: Mistaking the fstab src field for a host path; on macOS the value must be the macOS-automounted share name (the pseudo tag shown by Lima, e.g. the mount tag), not a filesystem path.

Related errors


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/04133b3c39002e0a. Report an issue: GitHub.