{"record":{"id":"1e5be5ce3d104dfe","repo":"apache/iceberg","slug":"cannot-apply-update-s-to-a-view","errorCode":null,"errorMessage":"Cannot apply update %s to a view","messagePattern":"Cannot apply update (.+?) to a view","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/MetadataUpdate.java","lineNumber":38,"sourceCode":"\nimport java.io.Serializable;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Set;\nimport org.apache.iceberg.encryption.EncryptedKey;\nimport org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;\nimport org.apache.iceberg.view.ViewMetadata;\nimport org.apache.iceberg.view.ViewVersion;\n\n/** Represents a change to table or view metadata. */\npublic interface MetadataUpdate extends Serializable {\n  default void applyTo(TableMetadata.Builder metadataBuilder) {\n    throw new UnsupportedOperationException(\n        String.format(\"Cannot apply update %s to a table\", this.getClass().getSimpleName()));\n  }\n\n  default void applyTo(ViewMetadata.Builder viewMetadataBuilder) {\n    throw new UnsupportedOperationException(\n        String.format(\"Cannot apply update %s to a view\", this.getClass().getSimpleName()));\n  }\n\n  class AssignUUID implements MetadataUpdate {\n    private final String uuid;\n\n    public AssignUUID(String uuid) {\n      this.uuid = uuid;\n    }\n\n    public String uuid() {\n      return uuid;\n    }\n\n    @Override\n    public void applyTo(TableMetadata.Builder metadataBuilder) {\n      metadataBuilder.assignUUID(uuid);\n    }","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/MetadataUpdate.java#L20-L56","documentation":"MetadataUpdate.applyTo has two default overloads: one for TableMetadata.Builder and one for ViewMetadata.Builder. Each default throws UnsupportedOperationException for the metadata kind it does not target. Seeing 'Cannot apply update %s to a view' means a table-only update (e.g. AssignUUID, AddSnapshot, SetSnapshotRef) was routed to a view metadata builder because every update type shares this interface and table-specific updates do not override the view overload.","triggerScenarios":"Calling applyTo(ViewMetadata.Builder) on a MetadataUpdate subclass that only overrides applyTo(TableMetadata.Builder), e.g. MetadataUpdate.AssignUUID, AddSnapshot, RemoveSnapshot, SetSnapshotRef, SetSnapshotSummary, UpgradeFormatVersion applied against a view, or a REST client applying an unrecognized/mismatched update fetched from a table's metadata log onto a view.","commonSituations":"REST catalog clients replaying metadata updates from a table location onto a view object; generic code that iterates a list of MetadataUpdate and applies them without checking whether they are view- or table-applicable; version mismatches where a new table-only update type is applied to views.","solutions":["Check the update kind before applying: skip or route table-only updates away from ViewMetadata.Builder (e.g. only apply updates whose class implements view support).","Ensure the update came from the correct entity — do not apply table metadata updates to view metadata.","If you control the code, override applyTo(ViewMetadata.Builder) in custom update types or dispatch via instanceof checks.","Upgrade Iceberg if this occurs with an update type that should support views (newer versions may add view support for more updates)."],"exampleFix":"// before\nfor (MetadataUpdate update : updates) {\n  update.applyTo(viewBuilder);\n}\n// after\nfor (MetadataUpdate update : updates) {\n  if (update instanceof MetadataUpdate.SetProperties\n      || update instanceof MetadataUpdate.RemoveProperties) {\n    update.applyTo(viewBuilder);\n  } // else: table-only update, skip for views\n}","handlingStrategy":"try-catch","validationCode":"boolean applicableToView = update instanceof MetadataUpdate.SetProperties\n    || update instanceof MetadataUpdate.RemoveProperties\n    || update instanceof MetadataUpdate.UpgradeFormatVersion;","typeGuard":"boolean isTableOnly = !(update instanceof MetadataUpdate.SetProperties)\n    && !(update instanceof MetadataUpdate.RemoveProperties)\n    && !(update instanceof MetadataUpdate.UpgradeFormatVersion);","tryCatchPattern":"try {\n  update.applyTo(viewMetadataBuilder);\n} catch (UnsupportedOperationException e) {\n  if (!e.getMessage().contains(\"to a view\")) throw e;\n  // skip or reroute table-only update\n}","preventionTips":["Route updates by entity kind before applying; never blindly replay a table's update log onto view metadata.","Maintain a whitelist of update types that apply to views.","Pin client and server Iceberg versions to compatible releases."],"tags":["unsupported-operation","metadata-update","view","java"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}