apache/iceberg · error · UnsupportedOperationException

Cannot update the location of a %s table

Error message

Cannot update the location of a %s table

What it means

Iceberg throws this UnsupportedOperationException when updateLocation() is called on a read-only table. Changing a table's storage location is a metadata write that BaseReadOnlyTable subclasses reject by design. The descriptor in the message names the read-only table kind.

Source

Thrown at core/src/main/java/org/apache/iceberg/BaseReadOnlyTable.java:55

    throw new UnsupportedOperationException(
        "Cannot update the partition spec of a " + descriptor + " table");
  }

  @Override
  public UpdateProperties updateProperties() {
    throw new UnsupportedOperationException(
        "Cannot update the properties of a " + descriptor + " table");
  }

  @Override
  public ReplaceSortOrder replaceSortOrder() {
    throw new UnsupportedOperationException(
        "Cannot update the sort order of a " + descriptor + " table");
  }

  @Override
  public UpdateLocation updateLocation() {
    throw new UnsupportedOperationException(
        "Cannot update the location of a " + descriptor + " table");
  }

  @Override
  public AppendFiles newAppend() {
    throw new UnsupportedOperationException("Cannot append to a " + descriptor + " table");
  }

  @Override
  public RewriteFiles newRewrite() {
    throw new UnsupportedOperationException("Cannot rewrite in a " + descriptor + " table");
  }

  @Override
  public RewriteManifests rewriteManifests() {
    throw new UnsupportedOperationException(
        "Cannot rewrite manifests in a " + descriptor + " table");
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Load the writable data table via catalog.loadTable(identifier) and call updateLocation() there.
  2. For relocation, some catalogs require creating the table at the new location or using catalog-level operations instead of updateLocation().
  3. Read the current location with table.location() instead of attempting to set it on a read-only view.

Example fix

// before
table.history().updateLocation().setTableLocation("s3://bucket/new-path").commit();

// after
Table dataTable = catalog.loadTable(TableIdentifier.of("db", "tbl"));
dataTable.updateLocation().setTableLocation("s3://bucket/new-path").commit();
Defensive patterns

Strategy: try-catch

Validate before calling

if (isMetadataTableName(table.name())) { throw new IllegalArgumentException("Cannot relocate metadata table " + table.name()); }

Type guard

boolean canSetLocation = !(table instanceof BaseReadOnlyTable); // ensure handle came from Catalog.loadTable

Try / catch

try {
  table.updateLocation().setTableLocation(newUri).commit();
} catch (UnsupportedOperationException e) {
  log.error("Location is not updatable on read-only table {}", table.name(), e);
}

Prevention

When it happens

Trigger: Calling table.updateLocation().setTableLocation(...) on a metadata table or any BaseReadOnlyTable subclass instance.

Common situations: Migration/relocation scripts that rewrite table locations against whatever Table object is in scope, hitting a metadata table handle instead of the data table.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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