chinabugotech/hutool · error · IORuntimeException

Not a file: {}

Error message

Not a file: {}

What it means

FileReader.checkFile() (called from the constructor) throws 'Not a file' when the File exists but file.isFile() is false, i.e. it is a directory or a non-regular (device/special) file. FileReader is designed to read regular files only and intentionally refuses directories. Like the not-exist check, this fires at construction time, before any read.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java:303

	 *
	 * @param <T> Reader处理返回结果类型
	 */
	public interface ReaderHandler<T> {
		T handle(BufferedReader reader) throws IOException;
	}
	// -------------------------------------------------------------------------- Interface end

	/**
	 * 检查文件
	 *
	 * @throws IORuntimeException IO异常
	 */
	private void checkFile() throws IORuntimeException {
		if (false == file.exists()) {
			throw new IORuntimeException("File not exist: " + file);
		}
		if (false == file.isFile()) {
			throw new IORuntimeException("Not a file:" + file);
		}
	}
}

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Point the FileReader at a specific regular file, not a directory.
  2. If you meant to read files inside a directory, list the entries (FileUtil.list / Files.list) and read each regular file individually.
  3. Validate with Files.isRegularFile(path) before constructing the reader.

Example fix

// before: 'logs' is a directory -> 'Not a file'
FileReader reader = FileReader.create(new File("/var/log/myapp"));

// after: target a specific file inside the directory
File target = new File("/var/log/myapp", "app.log");
if (!target.isFile()) {
    throw new IllegalStateException("Expected a regular file: " + target);
}
FileReader reader = FileReader.create(target);
Defensive patterns

Strategy: validation

Validate before calling

Path p = Paths.get(pathArg);
if (!Files.isRegularFile(p)) {
    throw new IllegalArgumentException(
        "Expected a regular file but got: " + p
        + (Files.isDirectory(p) ? " (it is a directory)" : ""));
}
FileReader reader = FileReader.create(p.toFile());

Type guard

boolean isRegularReadableFile(String path) {
    File f = new File(path);
    return f.isFile(); // true only for existing regular files
}

Try / catch

try {
    FileReader reader = FileReader.create(file);
} catch (IORuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Not a file")) {
        // user pointed at a directory/special file
        if (file.isDirectory()) {
            // iterate entries and read each regular file
        }
    }
    throw e;
}

Prevention

When it happens

Trigger: Constructing a FileReader (new FileReader(path) or FileReader.create(file)) where the path resolves to an existing directory, or to a non-regular file. Common when a folder path is passed where a file path was expected, or when a trailing slash / trailing segment makes the path a directory.

Common situations: Passing a directory path instead of a file path; misconfigured path that resolves to a folder; intending to read one file inside a directory but pointing at the directory itself; OS path differences where the same name is a directory on one platform.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/ce9d1315f1be1a69. Report an issue: GitHub.