lima-vm/lima · error

failed to read ssh public key %#q: %w

Error message

failed to read ssh public key %#q: %w

What it means

readPublicKey wraps os.ReadFile failures for an SSH public key file (such as $LIMA_HOME/_config/user.pub) with the file path and the underlying OS error. The entry is still returned with an empty Content so callers can see which file failed.

Source

Thrown at pkg/sshutil/sshutil.go:283

		return ""
	}
	return sftpServer
}

type PubKey struct {
	Filename string
	Content  string
}

func readPublicKey(f string) (PubKey, error) {
	entry := PubKey{
		Filename: f,
	}
	content, err := os.ReadFile(f)
	if err == nil {
		entry.Content = strings.TrimSpace(string(content))
	} else {
		err = fmt.Errorf("failed to read ssh public key %#q: %w", f, err)
	}
	return entry, err
}

// DefaultPubKeys returns the public key from $LIMA_HOME/_config/user.pub.
// The key will be created if it does not yet exist.
//
// When loadDotSSH is true, ~/.ssh/*.pub will be appended to make the VM accessible without specifying
// an identity explicitly.
func DefaultPubKeys(ctx context.Context, loadDotSSH bool) ([]PubKey, error) {
	// Read $LIMA_HOME/_config/user.pub
	configDir, err := dirnames.LimaConfigDir()
	if err != nil {
		return nil, err
	}
	_, err = os.Stat(filepath.Join(configDir, filenames.UserPrivateKey))
	if err != nil {
		if !errors.Is(err, os.ErrNotExist) {

View on GitHub (pinned to dd909d0973)

Solutions

  1. Check permissions on the key file: it should be readable by the current user (chmod 600, chown to your user).
  2. Regenerate the key pair with limactl or ssh-keygen if user.pub is corrupted or root-owned.
  3. Investigate the wrapped OS error (path printed in the message) for the concrete cause (ENOENT, EACCES, etc.).

Example fix

// before
sudo limactl start   # created _config/user.pub owned by root
// after
sudo chown -R "$USER" ~/.lima/_config
chmod 600 ~/.lima/_config/user
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat(pubKeyPath); err != nil { /* skip: key missing, let DefaultPubKeys create it */ }
if info, err := os.Stat(pubKeyPath); err == nil && !info.Mode().IsRegular() { /* not a normal file */ }

Type guard

func readable(f string) bool { h, err := os.Open(f); if err != nil { return false }; h.Close(); return true }

Try / catch

keys, err := sshutil.DefaultPubKeys(ctx)
if err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) { /* inspect pe.Path / pe.Err */ }
    return err
}

Prevention

When it happens

Trigger: DefaultPubKeys enumerates known public key files and calls readPublicKey; os.ReadFile fails with permission denied, an I/O error, or a race where the file disappears between existence check and read.

Common situations: _config/user.pub exists but is unreadable (wrong ownership/permissions, root-owned after sudo usage); file deleted concurrently; filesystem errors (full disk, broken symlink target).

Related errors


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