apache/seatunnel · error · IOException

Can't make directory for path "%s" under "%s".

Error message

Can't make directory for path "%s" under "%s".

What it means

mkdirs() attempts to create the leaf directory by cd'ing to the parent and calling client.mkdir(pathName). Any SftpException from that sequence is converted to IOException("Can't make directory for path \"%s\" under \"%s\".") — the SFTP server refused the MKDIR, typically because of permissions or because the entry already exists.

Source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/system/SFTPFileSystem.java:324

        } catch (SftpException e) {
            throw new IOException(e);
        }
        Path absolute = makeAbsolute(workDir, file);
        String pathName = absolute.getName();
        if (!exists(client, absolute)) {
            Path parent = absolute.getParent();
            created = parent == null || mkdirs(client, parent, FsPermission.getDefault());
            if (created) {
                String parentDir = parent.toUri().getPath();
                boolean succeeded = true;
                try {
                    final String previousCwd = client.pwd();
                    client.cd(parentDir);
                    LOG.debug("Creating directory " + pathName);
                    client.mkdir(pathName);
                    client.cd(previousCwd);
                } catch (SftpException e) {
                    throw new IOException(String.format(E_MAKE_DIR_FORPATH, pathName, parentDir));
                }
                created = created & succeeded;
            }
        } else if (isFile(client, absolute)) {
            throw new IOException(String.format(E_DIR_CREATE_FROMFILE, absolute));
        } else {
            LOG.debug("Skipping creation of existing directory " + file);
        }
        if (!created) {
            LOG.debug("Failed to create " + file);
        }
        return created;
    }

    private boolean isFile(ChannelSftp channel, Path file) throws IOException {
        try {
            return !getFileStatus(channel, file).isDirectory();
        } catch (FileNotFoundException e) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Grant the SFTP user write permission on the parent directory
  2. Check the server for quota or disk-space limits
  3. Handle 'already exists' benignly: verify with exists() before/after and ignore id-4 conflicts if the dir is present
  4. Ensure no concurrent jobs race to create the same path, or serialize creation
  5. Check the wrapped SftpException id in server/client logs for the precise cause

Example fix

// before
fs.mkdirs(new Path("/data/out")); // permission denied on /data
// after
// grant write on server: chown sftpuser /data && chmod u+w /data
chmod u+w /data
fs.mkdirs(new Path("/data/out"));
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: ensure parent writable by the account; server-side: sudo -u sftpuser test -w /data/parent
Path parent = path.getParent(); if (!fs.exists(parent)) fs.mkdirs(parent);

Try / catch

try { fs.mkdirs(p); } catch (IOException e) { if (fs.exists(p) && fs.getFileStatus(p).isDirectory()) { /* benign race: already created */ } else { throw e; } }

Prevention

When it happens

Trigger: client.mkdir() fails with permission denied (SFTP id 3), failure (id 4), or the directory already exists on servers that error instead of succeeding; also cd() to the parent failing mid-sequence.

Common situations: SFTP user lacks write permission on the parent directory; quota/disk-full on the server; concurrent jobs creating the same directory; read-only mounts on the server side.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/412895c58bbed9f4. Report an issue: GitHub.