apache/druid · error · UncheckedIOException
Unable to read file : %s
Error message
Unable to read file : %s
What it means
When reading back the written frame file, openChannel wraps any IOException from opening the remote input stream in an UncheckedIOException with message 'Unable to read file : %s'. The file path exists (checked earlier) but opening the read stream failed — typically a storage-client-level error.
Source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/shuffle/output/DurableStorageTaskOutputChannelFactory.java:140
try {
if (!storageConnector.pathExists(fileName)) {
throw new ISE("File does not exist : %s", fileName);
}
}
catch (Exception exception) {
throw new RuntimeException(exception);
}
try {
return ReadableInputStreamFrameChannel.open(
storageConnector.read(fileName),
fileName,
remoteInputStreamPool,
false,
wireTransferableContext
);
}
catch (IOException e) {
throw new UncheckedIOException(StringUtils.format("Unable to read file : %s", fileName), e);
}
},
partitionNumber
);
}
@Override
public PartitionedOutputChannel openPartitionedChannel(String name, boolean deleteAfterRead) throws IOException
{
final String fileName = DurableStorageUtils.getOutputsFileNameForPath(
controllerTaskId,
stageNumber,
workerNumber,
taskId,
name
);
final CountingOutputStream countingOutputStream = new CountingOutputStream(storageConnector.write(fileName));
final WritableFrameFileChannel writableChannel =View on GitHub (pinned to 9b90983fd2)
Solutions
- Look at the wrapped IOException cause for the storage-specific error code (access denied, throttled, not found).
- Verify credentials and IAM permissions for reading the durable-storage location.
- Add/increase retry and backoff settings on the storage connector client.
- Ensure deep-storage cleanup jobs are not deleting the query's intermediate prefix while the query runs.
Example fix
null
Defensive patterns
Strategy: retry
Validate before calling
// preflight read check on the storage location storageConnector.read(knownProbeKey).close(); // throws IOException early if credentials/permissions are broken
Try / catch
try {
readOutput();
} catch (UncheckedIOException e) {
if (isRetryable(e.getCause())) { retryWithBackoff(); } else { throw e; }
} Prevention
- Grant tasks read IAM permissions on the durable-storage prefix.
- Refresh credentials before expiry for long-running queries.
- Prevent cleanup jobs from deleting intermediate prefixes mid-query.
When it happens
Trigger: The read lambda in openChannel calls storageConnector.read / remoteInputStreamPool to open the partition output file and receives an IOException: transient deep-storage outage, permission/credential errors, file deleted between existence check and read, throttling by the object store.
Common situations: Expired cloud credentials (S3/GCS/Azure) mid-query; object-store throttling (429) during large shuffles; security/plugin misconfiguration denying read access; concurrent cleanup deleting the file.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Encountered error while reading the output of stage [%d], pa
- File does not exist : %s
- Could not find remote outputs of stage [%d] partition [%d] f
- No file present at the location [%s]. Unable to read the out
- Unable to read the task id from the file: [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/8aff5bce97a8d964.
Report an issue: GitHub.