{"record":{"id":"24caf6e2a3972c7e","repo":"apache/iceberg","slug":"not-implemented-dorefresh","errorCode":null,"errorMessage":"Not implemented: doRefresh","messagePattern":"Not implemented: doRefresh","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/BaseMetastoreTableOperations.java","lineNumber":105,"sourceCode":"    boolean currentMetadataWasAvailable = currentMetadata != null;\n    try {\n      doRefresh();\n    } catch (NoSuchTableException e) {\n      if (currentMetadataWasAvailable) {\n        LOG.warn(\"Could not find the table during refresh, setting current metadata to null\", e);\n        shouldRefresh = true;\n      }\n\n      currentMetadata = null;\n      currentMetadataLocation = null;\n      version = -1;\n      throw e;\n    }\n    return current();\n  }\n\n  protected void doRefresh() {\n    throw new UnsupportedOperationException(\"Not implemented: doRefresh\");\n  }\n\n  @Override\n  public void commit(TableMetadata base, TableMetadata metadata) {\n    // if the metadata is already out of date, reject it\n    if (base != current()) {\n      if (base != null) {\n        throw new CommitFailedException(\"Cannot commit: stale table metadata\");\n      } else {\n        // when current is non-null, the table exists. but when base is null, the commit is trying\n        // to create the table\n        throw new AlreadyExistsException(\"Table already exists: %s\", tableName());\n      }\n    }\n    // if the metadata is not changed, return early\n    if (base == metadata) {\n      LOG.info(\"Nothing to commit.\");\n      return;","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/BaseMetastoreTableOperations.java#L87-L123","documentation":"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.","triggerScenarios":"Calling refresh() (directly or via current()/commit paths that request a refresh) on a BaseMetastoreTableOperations subclass that does not override doRefresh.","commonSituations":"Custom catalog implementations that forgot to override doRefresh; using a base/anonymous operations class directly in tests; refactoring that dropped the override.","solutions":["Override doRefresh() in the concrete TableOperations subclass to fetch metadata from the metastore and set the current metadata","Ensure the catalog's newTableOps() returns the fully implemented operations class, not the base class","Update the custom catalog to the current BaseMetastoreTableOperations API and implement required hooks"],"exampleFix":"// before\nclass MyTableOperations extends BaseMetastoreTableOperations { }\n// after\nclass MyTableOperations extends BaseMetastoreTableOperations {\n  @Override\n  public void doRefresh() {\n    TableMetadata metadata = fetchMetadataFromMetastore();\n    this.currentMetadata = metadata;\n    this.currentMetadataLocation = metadata != null ? metadata.metadataFileLocation() : null;\n  }\n}","handlingStrategy":"type-guard","validationCode":"if (ops.getClass().getMethod(\"doRefresh\").getDeclaringClass() == BaseMetastoreTableOperations.class) { throw new IllegalStateException(\"Custom ops must override doRefresh\"); }","typeGuard":"static boolean supportsRefresh(TableOperations ops) { return !(ops instanceof BaseMetastoreTableOperations) || !ops.getClass().getName().equals(BaseMetastoreTableOperations.class.getName()); }","tryCatchPattern":"try { ops.refresh(); }\ncatch (UnsupportedOperationException e) { /* ops implementation incomplete; fix the catalog implementation */ }","preventionTips":["Always override doRefresh in BaseMetastoreTableOperations subclasses","Add a smoke test that refreshes a table through your custom catalog","Avoid instantiating base/abstract operations classes directly"],"tags":["unsupported-operation","custom-catalog","abstract-method"],"backgroundTag":"method-not-implemented","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}