lima-vm/lima · error

failed to create user %#q: %w

Error message

failed to create user %#q: %w

What it means

Raised by processUserData when creating one of the users listed in the user-data `users:` array fails on macOS. createUser performs several steps (sysadminctl -addUser, home directory population, SSH keys, sudoers), and the wrapped error identifies the failing step. The username is included via %#q.

Source

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

	if userData.PackageUpgrade {
		logrus.Warn("package_upgrade is not implemented")
	}
	if userData.PackageRebootIfRequired {
		logrus.Warn("package_reboot_if_required is not implemented")
	}
	for _, m := range userData.Mounts {
		if err = mountFSTabEntry(m); err != nil {
			errs = append(errs, fmt.Errorf("failed to mount fstab entry %v: %w", m, err))
		}
	}
	if userData.Timezone != "" {
		if err = setTimezone(ctx, userData.Timezone); err != nil {
			errs = append(errs, fmt.Errorf("failed to set timezone: %w", err))
		}
	}
	for _, u := range userData.Users {
		if err := createUser(ctx, &u); err != nil {
			errs = append(errs, fmt.Errorf("failed to create user %#q: %w", u.Name, err))
		}
	}
	for _, entry := range userData.WriteFiles {
		if err := writeFiles(ctx, entry); err != nil {
			errs = append(errs, fmt.Errorf("failed to write file for path %#q: %w", entry.Path, err))
		}
	}
	if userData.ManageResolvConf && userData.ResolvConf != nil {
		if err = setResolvConf(ctx, userData.ResolvConf); err != nil {
			errs = append(errs, fmt.Errorf("failed to apply DNS configuration: %w", err))
		}
	}
	if userData.CACerts != nil {
		logrus.Warn("ca_certs is not implemented")
	}
	if len(userData.BootCmd) > 0 {
		logrus.Warn("bootcmd is not implemented")
	}

View on GitHub (pinned to dd909d0973)

Solutions

  1. Read the wrapped error: it names the failing step (homedir required, uid required, invalid uid, sysadminctl, home dir, sudoers, etc.).
  2. Add `homedir` and a numeric `uid` to each users entry; both are mandatory in this fake cloud-init.
  3. Choose a UID that does not collide with existing macOS users.
  4. Ensure the sudo string is a single line without newline characters.
  5. If the user already exists (homedir present), creation is skipped automatically - verify the homedir path is not stale.

Example fix

// before (user-data)
users:
  - name: alice
// after
users:
  - name: alice
    homedir: /Users/alice
    uid: "501"
Defensive patterns

Strategy: validation

Validate before calling

func validateUsers(users []cloudinittypes.User) error {
  for i, u := range users {
    if u.Homedir == "" { return fmt.Errorf("users[%d] %q: homedir required", i, u.Name) }
    if _, err := strconv.Atoi(u.UID); err != nil { return fmt.Errorf("users[%d] %q: uid must be numeric", i, u.Name) }
    if strings.Contains(u.Sudo, "\n") { return fmt.Errorf("users[%d] %q: sudo must be single line", i, u.Name) }
  }
  return nil
}

Type guard

func isProvisionableUser(u *cloudinittypes.User) bool {
  return u.Name != "" && u.Homedir != "" && u.UID != ""
}

Try / catch

for _, u := range userData.Users {
  if err := createUser(ctx, &u); err != nil {
    log.Errorf("user %q skipped: %v", u.Name, err) // continue with remaining users
  }
}

Prevention

When it happens

Trigger: A `users:` entry lacks `homedir` or `uid` (both required by this implementation), the uid is not numeric, sysadminctl fails to add the user, or populating the home directory / writing password, .ssh, or sudoers files fails.

Common situations: Using the stock Linux cloud-init `default` user entry (no homedir/uid), picking a UID already in use by macOS (Setup Assistant users), or an invalid sudo config string containing newlines.

Related errors


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