apache/iceberg · error · UnsupportedOperationException

Not implemented: doRefresh

Error message

Not implemented: doRefresh

What it means

BaseMetastoreTableOperations.doRefresh() is an abstract extension point that subclasses override to reload current table metadata from their metastore. The base implementation throws UnsupportedOperationException, so calling refresh() on an operations instance that never wired up doRefresh fails immediately. It signals that the concrete catalog's operations class is incomplete or misused.

Solutions

  1. Override doRefresh() in the concrete TableOperations subclass to fetch metadata from the metastore and set the current metadata
  2. Ensure the catalog's newTableOps() returns the fully implemented operations class, not the base class
  3. Update the custom catalog to the current BaseMetastoreTableOperations API and implement required hooks

Example fix

// before
class MyTableOperations extends BaseMetastoreTableOperations { }
// after
class MyTableOperations extends BaseMetastoreTableOperations {
  @Override
  public void doRefresh() {
    TableMetadata metadata = fetchMetadataFromMetastore();
    this.currentMetadata = metadata;
    this.currentMetadataLocation = metadata != null ? metadata.metadataFileLocation() : null;
  }
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (ops.getClass().getMethod("doRefresh").getDeclaringClass() == BaseMetastoreTableOperations.class) { throw new IllegalStateException("Custom ops must override doRefresh"); }

Type guard

static boolean supportsRefresh(TableOperations ops) { return !(ops instanceof BaseMetastoreTableOperations) || !ops.getClass().getName().equals(BaseMetastoreTableOperations.class.getName()); }

Try / catch

try { ops.refresh(); }
catch (UnsupportedOperationException e) { /* ops implementation incomplete; fix the catalog implementation */ }

Prevention

When it happens

Trigger: Calling refresh() (directly or via current()/commit paths that request a refresh) on a BaseMetastoreTableOperations subclass that does not override doRefresh.

Common situations: Custom catalog implementations that forgot to override doRefresh; using a base/anonymous operations class directly in tests; refactoring that dropped the override.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/24caf6e2a3972c7e. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/BaseMetastoreTableOperations.java:105

    boolean currentMetadataWasAvailable = currentMetadata != null;
    try {
      doRefresh();
    } catch (NoSuchTableException e) {
      if (currentMetadataWasAvailable) {
        LOG.warn("Could not find the table during refresh, setting current metadata to null", e);
        shouldRefresh = true;
      }

      currentMetadata = null;
      currentMetadataLocation = null;
      version = -1;
      throw e;
    }
    return current();
  }

  protected void doRefresh() {
    throw new UnsupportedOperationException("Not implemented: doRefresh");
  }

  @Override
  public void commit(TableMetadata base, TableMetadata metadata) {
    // if the metadata is already out of date, reject it
    if (base != current()) {
      if (base != null) {
        throw new CommitFailedException("Cannot commit: stale table metadata");
      } else {
        // when current is non-null, the table exists. but when base is null, the commit is trying
        // to create the table
        throw new AlreadyExistsException("Table already exists: %s", tableName());
      }
    }
    // if the metadata is not changed, return early
    if (base == metadata) {
      LOG.info("Nothing to commit.");
      return;

View on GitHub (pinned to 86d9c8fc54)