{"record":{"id":"6f8a4924d93543b0","repo":"apache/iceberg","slug":"cannot-create-a-transaction-within-a-transaction","errorCode":null,"errorMessage":"Cannot create a transaction within a transaction","messagePattern":"Cannot create a transaction within a transaction","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/BaseTransaction.java","lineNumber":690,"sourceCode":"    @Override\n    public UpdatePartitionStatistics updatePartitionStatistics() {\n      return BaseTransaction.this.updatePartitionStatistics();\n    }\n\n    @Override\n    public ExpireSnapshots expireSnapshots() {\n      return BaseTransaction.this.expireSnapshots();\n    }\n\n    @Override\n    public ManageSnapshots manageSnapshots() {\n      throw new UnsupportedOperationException(\n          \"Transaction tables do not support managing snapshots\");\n    }\n\n    @Override\n    public Transaction newTransaction() {\n      throw new UnsupportedOperationException(\"Cannot create a transaction within a transaction\");\n    }\n\n    @Override\n    public FileIO io() {\n      return transactionOps.io();\n    }\n\n    @Override\n    public EncryptionManager encryption() {\n      return transactionOps.encryption();\n    }\n\n    @Override\n    public LocationProvider locationProvider() {\n      return transactionOps.locationProvider();\n    }\n\n    @Override","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/BaseTransaction.java#L672-L708","documentation":"Iceberg does not allow nested transactions. Calling newTransaction() on the TransactionTable view inside an open transaction throws UnsupportedOperationException. Transactions must be flat: finish the outer transaction before starting another one.","triggerScenarios":"Calling newTransaction() where the Table handle is the one returned by an active Transaction's table() method; helper code that opens transactions on whatever Table it receives.","commonSituations":"Composable write utilities that each open their own transaction being combined inside a caller's transaction; framework code that wraps Table generically.","solutions":["Reuse the existing transaction: add updates to the outer Transaction instead of opening a new one","Commit the outer transaction before starting a new one","Refactor helpers to accept a Transaction instead of a Table when called inside transactional code"],"exampleFix":"// before\nTransaction tx = table.newTransaction();\nTransaction inner = tx.table().newTransaction(); // throws\n// after\nTransaction tx = table.newTransaction();\ntx.updateSchema().addColumn(\"c\", Types.LongType.get()).commit(); // reuse outer tx\ntx.commitTransaction();","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function canStartTransaction(table) { return !(table instanceof BaseTransaction.TransactionTable); }","tryCatchPattern":"catch (UnsupportedOperationException e) { /* reuse existing transaction passed via parameter */ }","preventionTips":["Pass the active Transaction into helper methods rather than a Table","Design write utilities to optionally join a caller-provided transaction","Never hold a Transaction.table() reference in code that opens transactions"],"tags":["unsupported-operation","transaction","nesting"],"backgroundTag":"invalid-state-transition","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"}