apache/druid · error · java.io.FileNotFoundException
Unable to find file for reading
Error message
Unable to find file %s for reading
What it means
LocalFileStorageConnector.readRange throws FileNotFoundException when the requested relative path does not exist under the connector's base path. It means a read of a byte range was requested for a file absent from local storage.
Solutions
- Confirm the exact relative path exists under the base path (ls); fix typos/case mismatches.
- Re-fetch or re-download the segment/file (trigger re-load or re-run export) since it may have been cleaned up.
- Check retention/cleanup jobs that may have deleted the file concurrently.
- Validate file existence before issuing range reads and handle FileNotFoundException explicitly in callers.
Example fix
// before
InputStream in = connector.readRange("export/2024/result.csv", 0, 1024); // file deleted
// after
File f = new File(basePath, "export/2024/result.csv");
if (!f.isFile()) {
throw new FileNotFoundException("regenerate export: missing " + f);
}
InputStream in = connector.readRange("export/2024/result.csv", 0, 1024); Defensive patterns
Strategy: try-catch
Validate before calling
if (!new File(basePath, path).isFile()) throw new FileNotFoundException(path);
Type guard
boolean exists(StorageConnector c, String p) { try { return c.pathExists(p); } catch (IOException e) { return false; } } Try / catch
try { in = connector.readRange(path, from, size); } catch (FileNotFoundException e) { log.warn(e, "file missing: %s", path); in = regenerateAndReopen(path); } Prevention
- Check pathExists before range reads.
- Coordinate retention/cleanup jobs with consumers of the files.
- Verify path casing on case-sensitive filesystems.
- Re-trigger loads/exports instead of assuming files persist.
When it happens
Trigger: readRange(path, from, size) where pathExists(path) is false: file deleted (e.g. by cleanup/kill tasks), wrong relative path, segment not yet downloaded to local cache, typo or case-mismatch on the path.
Common situations: Segment files cleaned up while a task still needs them; querying an export file that finished/was removed; path casing differences on case-sensitive filesystems; load rule dropped the segment from the historical's cache.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Asked to load path[ ], but it doesn't exist.
- Can't find field [ ] with name [ ] in [ ] file.
- Could not find match for pattern
- Extension [ ] specified in "druid.extensions.loadList"…
- File[ ] not found
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/6377bbc60c799951.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/storage/local/LocalFileStorageConnector.java:74
}
@Override
public boolean pathExists(String path)
{
return fileWithBasePath(path).exists();
}
@Override
public InputStream read(String path) throws IOException
{
return Files.newInputStream(fileWithBasePath(path).toPath());
}
@Override
public InputStream readRange(String path, long from, long size) throws IOException
{
if (!pathExists(path)) {
throw new FileNotFoundException("Unable to find file " + fileWithBasePath(path).toPath() + " for reading");
}
long length = fileWithBasePath(path).length();
if (from < 0 || size < 0 || (from + size) > length) {
throw new IAE(
"Invalid arguments for reading %s. from = %d, readSize = %d, fileSize = %d",
fileWithBasePath(path).toPath(),
from,
size,
length
);
}
FileChannel fileChannel = FileChannel.open(fileWithBasePath(path).toPath(), StandardOpenOption.READ);
return new BoundedInputStream(Channels.newInputStream(fileChannel.position(from)), size);
}
/**
* Writes the file present with the materialized location as basePath + path.
* In case the parent directory does not exist, we create the parent dir recursively.View on GitHub (pinned to 9b90983fd2)