apache/druid · error · IOException (IOE)
Could not fetch last modified timestamp from URI [%s]
Error message
Could not fetch last modified timestamp from URI [%s]
What it means
S3DataSegmentPuller.getVersion fetches an S3 object's metadata to read its last-modified timestamp as the segment version string. When the S3 SDK raises an SdkException classified as recoverable, it is wrapped in an IOException with this message. Recoverable means the caller may succeed on retry.
Source
Thrown at extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentPuller.java:311
*
* @param uri The URI to check the last timestamp
* @return The time in ms of the last modification of the URI in String format
* @throws IOException
*/
@Override
public String getVersion(URI uri) throws IOException
{
try {
final CloudObjectLocation coords = new CloudObjectLocation(S3Utils.checkURI(uri));
final HeadObjectResponse objectMetadata =
S3Utils.getSingleObjectMetadata(s3Client, coords.getBucket(), coords.getPath());
Instant lastModified = objectMetadata.lastModified();
return StringUtils.format("%d", lastModified != null ? lastModified.toEpochMilli() : 0L);
}
catch (SdkException e) {
if (AWSClientUtil.isClientExceptionRecoverable(e)) {
// The recoverable logic is always true for IOException, so we want to only pass IOException if it is recoverable
throw new IOE(e, "Could not fetch last modified timestamp from URI [%s]", uri);
} else {
throw new RE(e, "Error fetching last modified timestamp from URI [%s]", uri);
}
}
}
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Retry the operation; the error is explicitly marked recoverable.
- Verify S3 connectivity/endpoint configuration (region, proxy, VPC endpoints).
- Check IAM credentials validity and that the bucket/key exist.
- Inspect the wrapped SdkException cause for the root AWS error code.
Example fix
// before String v = puller.getVersion(uri); // after String v = RetryUtils.retry(() -> puller.getVersion(uri), s -> s instanceof IOException);
Defensive patterns
Strategy: retry
Validate before calling
if (!S3Utils.isObjectInBucket(s3Client, bucket, key)) throw new IllegalStateException("missing object"); Try / catch
try { v = puller.getVersion(uri); } catch (IOException e) { /* recoverable: retry with backoff */ v = RetryUtils.retry(() -> puller.getVersion(uri), s -> true); } Prevention
- Retry recoverable IOEs with backoff
- Monitor S3 error rates and configure retries on the S3 client
- Validate segment URIs before loading
When it happens
Trigger: Calling version()/getVersion() on a segment URI when the S3 HeadObject call throws a recoverable SdkException (transient network failure, throttling, 5xx, connection reset).
Common situations: Transient S3 outages or throttling during historical segment loading; misconfigured proxy or DNS causing intermittent connectivity failures; expired credentials sometimes surfacing as recoverable SDK errors.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Failed to get object summaries from S3 bucket[%s], prefix[%s
- Couldn't delete segments from S3. See the task logs for more
- Couldn't kill segment[%s]: [%s]
- Unable to move segment[%s]: [%s]
- Error fetching last modified timestamp from URI [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/9105fec199b7dc94.
Report an issue: GitHub.