apache/seatunnel · error · IOException

Can't make directory for path %s since it is a file.

Error message

Can't make directory for path %s since it is a file.

What it means

When the target path of mkdirs() already exists as a regular file, the code throws IOException("Can't make directory for path %s since it is a file."). It is a path-type conflict: a directory operation was requested on something that is not a directory.

Source

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

        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) {
            return false; // file does not exist
        } catch (IOException ioe) {
            throw new IOException(E_FILE_CHECK_FAILED, ioe);
        }
    }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove or rename the existing file at that path so the directory can be created
  2. Fix the configured output/directory path so it does not collide with a file
  3. Verify with fs.isFile() or getFileStatus().isDirectory() before calling mkdirs in custom code
  4. Clean stale state from previous runs instead of reusing the same base path

Example fix

// before
fs.mkdirs(new Path("/data/out")); // /data/out is an existing file
// after
Path out = new Path("/data/out");
if (fs.isFile(out)) { // or getFileStatus(out).isDirectory() == false
    fs.delete(out, false); // remove conflicting file
}
fs.mkdirs(out);
Defensive patterns

Strategy: validation

Validate before calling

Path p = new Path("/data/out"); if (fs.exists(p) && fs.getFileStatus(p).isDirectory() == false) { throw new IllegalStateException("Path is a file: " + p); }

Try / catch

try { fs.mkdirs(p); } catch (IOException e) { throw new IllegalStateException("Output path conflicts with an existing file: " + p, e); }

Prevention

When it happens

Trigger: mkdirs() (directly, via create()'s implicit parent creation, or via a recursive parent step) finds the existing entry isFile() == true.

Common situations: A file was previously written at the exact path where a directory is now required (e.g. output path collides with a marker file); wrong configured output path pointing to a file; leftover file from a previous run with a changed schema layout.

Related errors


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