lima-vm/lima · error

failed to create the synced workdir in guest instance

Error message

failed to create the synced workdir in guest instance: %w

What it means

With `--sync`, Lima first creates the destination directory inside the guest (`mkdir -p <destRsyncDir>`) over SSH before invoking rsync — quoting via `--rsync-path` is deliberately avoided as harder to get right. If that SSH command fails (connection problem, authentication failure, remote mkdir error), the error is wrapped with this message.

Solutions

  1. Confirm the instance is running (`limactl list`) and start it with `limactl start <instance>` if not.
  2. Retry after a moment if the guest was just booted (SSH daemon may not be ready).
  3. Check guest home permissions/disk space (`limactl shell <instance> df -h; ls -ld ~`) and fix mkdir failures.
  4. Run with `--debug` to inspect the underlying SSH error for connection/auth specifics.

Example fix

# before
limactl shell stopped-instance --sync .
# after
limactl start stopped-instance
limactl shell stopped-instance --sync .
Defensive patterns

Strategy: retry

Validate before calling

limactl list | grep -q "^$inst.*Running" || { echo 'instance not running'; exit 1; }

Type guard

null

Try / catch

for i in 1 2 3; do limactl shell "$inst" --sync . && break; sleep $((i*5)); done

Prevention

When it happens

Trigger: `--sync` is active and `executeSSHForRsync` runs `mkdir -p <destRsyncDir>` at the instance's SSHLocalPort/SSHAddress, and the SSH execution fails: instance not running, port forwarding broken, permission denied creating the directory under the guest user's home.

Common situations: Instance stopped or crashed between `limactl start` and the shell command; SSH daemon not ready yet; guest disk full or home directory read-only making `mkdir -p` fail; wrong SSH port after a port conflict.

Related errors


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

Appendix: source

Thrown at cmd/limactl/shell.go:430

		// Only remove these options when writing the SSH config file and executing `limactl shell`, since multiplexing seems to work with port forwarding.
		sshOpts = sshutil.SSHOptsRemovingControlPath(sshOpts)
	}
	sshArgs := append([]string{}, sshExe.Args...)
	sshArgs = append(sshArgs, sshutil.SSHArgsFromOpts(sshOpts)...)

	var (
		sshExecForRsync *exec.Cmd
		rsync           copytool.CopyTool
	)
	if syncHostWorkdir {
		logrus.Infof("Syncing host current directory(%s) to guest instance...", hostCurrentDir)
		sshExecForRsync = exec.CommandContext(ctx, sshExe.Exe, sshArgs...)

		// Create the destination directory in the guest instance,
		// we could have done this by using `--rsync-path` but it's more
		// complex to quote properly.
		if err := executeSSHForRsync(ctx, *sshExecForRsync, inst.SSHLocalPort, inst.SSHAddress, fmt.Sprintf("mkdir -p %s", shellescape.Quote(destRsyncDir))); err != nil {
			return fmt.Errorf("failed to create the synced workdir in guest instance: %w", err)
		}

		// Quote the destination path for rsync versions before 3.2.4, where --protect-args is not the default
		// and the remote shell would split paths containing spaces.
		rsyncVer, err := rsyncVersion(ctx)
		if err != nil {
			return fmt.Errorf("failed to get rsync version: %w", err)
		}
		if rsyncVer.LessThan(*semver.New("3.2.4")) {
			destRsyncDir = shellescape.Quote(destRsyncDir)
		}

		paths := []string{
			hostCurrentDir,
			fmt.Sprintf("%s:%s", inst.Name, destRsyncDir),
		}
		rsync, err = copytool.New(ctx, string(copytool.BackendRsync), paths, &copytool.Options{
			Recursive: true,

View on GitHub (pinned to dd909d0973)