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
- Point the FileReader at a specific regular file, not a directory.
- If you meant to read files inside a directory, list the entries (FileUtil.list / Files.list) and read each regular file individually.
- 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
- Always pass a specific file path, not a directory, to FileReader.
- Validate Files.isRegularFile before constructing a reader.
- When accepting user input, reject directory paths early with a clear message.
- For directory reads, list entries first and read each regular file individually.
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
- Src [{}] is a directory but dest [{}] is a file!
- File not exist: {}
- Path [{}] is not directory!
- File is larger then max array size
- File length is [{}] but read [{}]!
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/ce9d1315f1be1a69.
Report an issue: GitHub.