{"record":{"id":"9e7c57819849fc44","repo":"apache/iceberg","slug":"cannot-append-to-a-s-table","errorCode":null,"errorMessage":"Cannot append to a %s table","messagePattern":"Cannot append to a (.+?) table","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/BaseReadOnlyTable.java","lineNumber":61,"sourceCode":"    throw new UnsupportedOperationException(\n        \"Cannot update the properties of a \" + descriptor + \" table\");\n  }\n\n  @Override\n  public ReplaceSortOrder replaceSortOrder() {\n    throw new UnsupportedOperationException(\n        \"Cannot update the sort order of a \" + descriptor + \" table\");\n  }\n\n  @Override\n  public UpdateLocation updateLocation() {\n    throw new UnsupportedOperationException(\n        \"Cannot update the location of a \" + descriptor + \" table\");\n  }\n\n  @Override\n  public AppendFiles newAppend() {\n    throw new UnsupportedOperationException(\"Cannot append to a \" + descriptor + \" table\");\n  }\n\n  @Override\n  public RewriteFiles newRewrite() {\n    throw new UnsupportedOperationException(\"Cannot rewrite in a \" + descriptor + \" table\");\n  }\n\n  @Override\n  public RewriteManifests rewriteManifests() {\n    throw new UnsupportedOperationException(\n        \"Cannot rewrite manifests in a \" + descriptor + \" table\");\n  }\n\n  @Override\n  public OverwriteFiles newOverwrite() {\n    throw new UnsupportedOperationException(\"Cannot overwrite in a \" + descriptor + \" table\");\n  }\n","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/BaseReadOnlyTable.java#L43-L79","documentation":"Iceberg throws this UnsupportedOperationException when newAppend() is called on a read-only table. Appending data files produces a new snapshot, a write operation that BaseReadOnlyTable subclasses (metadata tables, read-only views) never permit. The descriptor names the read-only table kind.","triggerScenarios":"Calling table.newAppend().appendFile(...).commit() on a metadata table (e.g. table.snapshots()) or any other BaseReadOnlyTable subclass.","commonSituations":"Ingestion pipelines that resolve a Table object by name and accidentally bind a metadata-table reference, or generic writer code applied to read-only views.","solutions":["Append to the writable data table loaded from the catalog, not the metadata-table handle.","Verify which Table instance the writer holds before calling newAppend().","If the intent was writing to a view's underlying table, load the base table explicitly."],"exampleFix":"// before\ntable.snapshots().newAppend().appendFile(dataFile).commit();\n\n// after\nTable dataTable = catalog.loadTable(TableIdentifier.of(\"db\", \"tbl\"));\ndataTable.newAppend().appendFile(dataFile).commit();","handlingStrategy":"try-catch","validationCode":"if (isMetadataTableName(table.name())) { throw new IllegalArgumentException(\"Cannot append to metadata table \" + table.name()); }","typeGuard":"boolean canAppend = !(table instanceof BaseReadOnlyTable); // ensure handle came from Catalog.loadTable","tryCatchPattern":"try {\n  table.newAppend().appendFile(file).commit();\n} catch (UnsupportedOperationException e) {\n  log.error(\"Cannot append to read-only table {}\", table.name(), e);\n}","preventionTips":["Bind writers to catalog-loaded data tables only.","Avoid storing Table handles loosely; store identifiers and load when writing.","Review dependency injection that might supply a metadata-table handle to writers."],"tags":["unsupported-operation","write-path","read-only-table"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}