kubernetes/kops · error

error creating directory %q over sftp: %w

Error message

error creating directory %q over sftp: %w

What it means

After ensuring the parent directory exists, mkdirAll attempts sftpClient.Mkdir(dir) to create the leaf directory. If the SFTP server rejects the Mkdir, the underlying error is wrapped with this message. Common underlying causes are EPERM/EACCES (no write permission on the parent) or the directory appearing concurrently.

Source

Thrown at util/pkg/vfs/sshfs.go:166

	}

	stat, err := sftpClient.Lstat(dir)
	if err == nil {
		if !stat.IsDir() {
			return fmt.Errorf("not a directory: %q", dir)
		}
		return nil
	}

	parent := path.Dir(dir)
	err = mkdirAll(sftpClient, parent)
	if err != nil {
		return err
	}

	err = sftpClient.Mkdir(dir)
	if err != nil {
		return fmt.Errorf("error creating directory %q over sftp: %w", dir, err)
	}
	return nil
}

func (p *SSHPath) WriteFile(ctx context.Context, data io.ReadSeeker, acl ACL) error {
	sftpClient, err := p.newClient(ctx)
	if err != nil {
		return err
	}
	defer sftpClient.Close()

	dir := path.Dir(p.path)
	err = mkdirAll(sftpClient, dir)
	if err != nil {
		return err
	}

	tempfile := path.Join(dir, fmt.Sprintf(".tmp-%d", rand.Int63()))

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check permissions of the parent directory on the remote host and grant write access (`chmod`/`chown`) or run kOps as a user with sufficient rights.
  2. If permission is the issue and the command supports it, target a path the SSH user can write, or pre-create the directory as root via SSH: `sudo mkdir -p <dir>`.
  3. Check for EEXIST in the wrapped error — if the directory was created concurrently, simply retry the operation.
  4. Verify the remote filesystem is writable (not read-only, not full): `touch <dir>/.write-test` over SSH.

Example fix

// before: sftp user cannot create /etc/kubernetes/manifests
sshfs.NewSSHPath(client, server, "/etc/kubernetes/manifests/file", false)
// after: pre-create with elevated rights, then write over sftp
$ ssh host 'sudo mkdir -p /etc/kubernetes/manifests && sudo chown sftpuser /etc/kubernetes/manifests'
Defensive patterns

Strategy: retry

Validate before calling

// ensure the SSH user can create directories under the parent
session := sshRun(host, "test -w $(dirname /etc/kubernetes/manifests) && echo writable")
// expect output "writable"

Try / catch

err := path.WriteFile(ctx, data, acl)
if err != nil && strings.Contains(err.Error(), "error creating directory") {
    var sftpErr *sftp.StatusError
    if errors.As(err, &sftpErr) && sftpErr.Code == uint32(sftp.ErrSSHFxPermissionDenied) {
        return fmt.Errorf("fix remote permissions or pre-create dir: %w", err)
    }
}

Prevention

When it happens

Trigger: WriteFile -> mkdirAll -> sftpClient.Mkdir fails because the SSH user lacks write permission on the parent directory, the filesystem is read-only, or a race created the directory between Lstat and Mkdir (EEXIST).

Common situations: Deploying to a host where the SSH user is not root and lacks sudo (sudo only helps the shell `mv` path, not SFTP); read-only root filesystem on a node; disk full; SELinux/AppArmor denying the SFTP subsystem write.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/627b85e0363ef790. Report an issue: GitHub.