{"record":{"id":"4221bc1cc6378e8e","repo":"apache/iceberg","slug":"transaction-tables-do-not-support-scans","errorCode":null,"errorMessage":"Transaction tables do not support scans","messagePattern":"Transaction tables do not support scans","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/BaseTransaction.java","lineNumber":539,"sourceCode":"\n  public class TransactionTable implements Table, HasTableOperations, Serializable {\n\n    @Override\n    public TableOperations operations() {\n      return transactionOps;\n    }\n\n    @Override\n    public String name() {\n      return tableName;\n    }\n\n    @Override\n    public void refresh() {}\n\n    @Override\n    public TableScan newScan() {\n      throw new UnsupportedOperationException(\"Transaction tables do not support scans\");\n    }\n\n    @Override\n    public Schema schema() {\n      return current.schema();\n    }\n\n    @Override\n    public Map<Integer, Schema> schemas() {\n      return current.schemasById();\n    }\n\n    @Override\n    public PartitionSpec spec() {\n      return current.spec();\n    }\n\n    @Override","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/BaseTransaction.java#L521-L557","documentation":"The TransactionTable view exposed inside an open transaction deliberately does not support scans. newScan() throws UnsupportedOperationException because reads must be performed against the committed table, not against in-transaction (uncommitted) metadata. The transaction table implementation is write-only within the transaction scope.","triggerScenarios":"Calling newScan() on the Table returned by Transaction.table(), or any API that internally scans, while inside table.newTransaction().","commonSituations":"Developers trying to read data written earlier in the same transaction to verify it; copy-on-write merge logic attempting a scan inside a transaction; generic code paths that assume every Table supports scans.","solutions":["Perform reads against the outer Table object (before the transaction or after commit)","Split the workflow: scan the committed table, then open a transaction for writes","Restructure code so read paths receive the base Table, not Transaction.table()"],"exampleFix":"// before\nTransaction tx = table.newTransaction();\nTableScan scan = tx.table().newScan(); // throws\n// after\nTableScan scan = table.newScan(); // read from committed table\nTransaction tx = table.newTransaction();\n// ... write via tx ...\ntx.commitTransaction();","handlingStrategy":"validation","validationCode":"if (isTransactionTable(table)) { throw new IllegalStateException(\"Use the outer table for scans\"); }","typeGuard":null,"tryCatchPattern":"catch (UnsupportedOperationException e) { scanOuterTable(); }","preventionTips":["Never call read/scan APIs on Transaction.table(); only use it for writes","Keep read and write phases of a workflow clearly separated","Wrap Transaction.table() in a write-only facade to prevent accidental scans"],"tags":["unsupported-operation","transaction","scan"],"backgroundTag":"operation-not-supported","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"}