apache/druid · error · RuntimeException (RE)
Error fetching last modified timestamp from URI [%s]
Error message
Error fetching last modified timestamp from URI [%s]
What it means
Same code path as the recoverable variant, but thrown when the SdkException from the HeadObject call is classified as non-recoverable. It is wrapped in a RuntimeException (RE) because retrying is not expected to help.
Source
Thrown at extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentPuller.java:313
* @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
- Verify the segment URI (bucket/key) exists in S3.
- Check IAM credentials and policy for s3:GetObject/s3:ListBucket permissions.
- Confirm the configured region/endpoint matches the bucket's region.
- Fix the underlying configuration; do not retry, the error is permanent.
Example fix
// before
String v = puller.getVersion(maybeMissingUri);
// after
if (S3Utils.isObjectInBucket(s3Client, bucket, key)) {
String v = puller.getVersion(maybeMissingUri);
} Defensive patterns
Strategy: try-catch
Validate before calling
boolean exists = S3Utils.isObjectInBucket(s3Client, bucket, key);
Try / catch
try { v = puller.getVersion(uri); } catch (RuntimeException e) { log.error("Permanent failure fetching %s", uri, e); throw e; } Prevention
- Verify segment existence before metadata fetch
- Audit IAM policies for s3:GetObject
- Keep segment metadata and S3 objects in sync (don't delete during queries)
When it happens
Trigger: Calling version()/getVersion() when S3 returns a permanent error: 404 NoSuchKey/403 AccessDenied, invalid credentials, malformed request, or other non-retryable SDK failures.
Common situations: Segment descriptor points to a deleted or never-uploaded object; wrong bucket or region configuration; IAM policy missing s3:GetObject on the segment prefix.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Failed to get object summaries from S3 bucket[%s], prefix[%s
- 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]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/f6096f7d2a505101.
Report an issue: GitHub.