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
- 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.
- 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>`.
- Check for EEXIST in the wrapped error — if the directory was created concurrently, simply retry the operation.
- 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
- Provision the SFTP/SSH user with write access to all target directories up front.
- Pre-create directory trees with correct ownership in your provisioning pipeline.
- Treat EEXIST as benign and retry once on concurrent-create races.
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
- error during chmod of %q: %w
- removing destination sftp file %q before rename: %w
- error creating sftp client: %w
- error creating sftp client (in new-session): %w
- error creating sftp client (at stdin pipe): %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/627b85e0363ef790.
Report an issue: GitHub.