apache/iceberg · error · UnsupportedOperationException
does not support caching
Error message
does not support caching
What it means
BaseDeleteLoader.getOrLoad is a hook for subclasses that implement delete-file caching; the base implementation does not cache and throws UnsupportedOperationException if called. It is only invoked after canCache(long) returned true, so calling this indicates a subclass claims caching support without implementing getOrLoad.
Solutions
- Implement getOrLoad in your subclass with an actual cache (e.g. Caffeine) honoring valueSize
- Return false from canCache if caching is not implemented
- Use a built-in loader subclass that supports caching
Example fix
// before
@Override
public boolean canCache(long contentSizeInBytes) {
return true; // but getOrLoad not implemented
}
// after
@Override
public boolean canCache(long contentSizeInBytes) {
return cache != null && contentSizeInBytes <= maxEntrySize;
}
@Override
protected <V> V getOrLoad(String key, Supplier<V> valueSupplier, long valueSize) {
return cache.get(key, k -> valueSupplier.get());
} Defensive patterns
Strategy: validation
Validate before calling
if (canCache(size) && getClass().getMethod("getOrLoad", String.class, Supplier.class, long.class).getDeclaringClass() == BaseDeleteLoader.class) { throw new IllegalStateException("caching enabled without getOrLoad override"); } Try / catch
try { loader.getOrLoad(key, supplier, size); } catch (UnsupportedOperationException e) { // fall back to uncached read } Prevention
- Never override canCache to return true without implementing getOrLoad
- Unit-test custom delete loaders with caching enabled
- Prefer built-in cached loader implementations over custom cache plumbing
When it happens
Trigger: A subclass of BaseDeleteLoader overrides canCache to return true but does not override getOrLoad; then getOrReadEqDeletes or indexes calls getOrLoad and hits the default throwing implementation.
Common situations: Custom delete loader implementations enabling caching incorrectly; copying a canCache override from another loader (e.g. a Spark cached loader) without the cache plumbing.
Related errors
- An error occurred reloading table
- An error occurred reloading table
- Invalid (NOT_MODIFIED) response for request: method=
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/713de8310ca2c224.
Report an issue: GitHub.
Appendix: source
Thrown at data/src/main/java/org/apache/iceberg/data/BaseDeleteLoader.java:96
* to use the provided size as a guideline to decide whether the value is eligible for caching.
* For instance, it may be beneficial to discard values that are too large to optimize the cache
* performance and utilization.
*/
protected boolean canCache(long size) {
return false;
}
/**
* Gets the cached value for the key or populates the cache with a new mapping.
*
* <p>If the value for the specified key is in the cache, it should be returned. If the value is
* not in the cache, implementations should compute the value using the provided supplier, cache
* it, and then return it.
*
* <p>This method will be called only if {@link #canCache(long)} returned true.
*/
protected <V> V getOrLoad(String key, Supplier<V> valueSupplier, long valueSize) {
throw new UnsupportedOperationException(getClass().getName() + " does not support caching");
}
@Override
public StructLikeSet loadEqualityDeletes(Iterable<DeleteFile> deleteFiles, Schema projection) {
Iterable<Iterable<StructLike>> deletes =
execute(deleteFiles, deleteFile -> getOrReadEqDeletes(deleteFile, projection));
StructLikeSet deleteSet = StructLikeSet.create(projection.asStruct());
Iterables.addAll(deleteSet, Iterables.concat(deletes));
return deleteSet;
}
private Iterable<StructLike> getOrReadEqDeletes(DeleteFile deleteFile, Schema projection) {
long estimatedSize = estimateEqDeletesSize(deleteFile, projection);
if (canCache(estimatedSize)) {
String cacheKey = deleteFile.location();
return getOrLoad(cacheKey, () -> readEqDeletes(deleteFile, projection), estimatedSize);
} else {
return readEqDeletes(deleteFile, projection);View on GitHub (pinned to 86d9c8fc54)