This is an automated email from the ASF dual-hosted git repository.

laskoviymishka pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git


The following commit(s) were added to refs/heads/main by this push:
     new c64f9a79d refactor(table)!: return branch transaction initialization 
errors directly (#2313)
c64f9a79d is described below

commit c64f9a79dc25fd4fdf76f4293ef22d3d1632d520
Author: Minh Vu <[email protected]>
AuthorDate: Sun Oct 25 21:03:22 2026 +0100

    refactor(table)!: return branch transaction initialization errors directly 
(#2313)
---
 table/branch_planning_test.go        | 40 +++++++++++------------
 table/rewrite_data_files.go          |  4 +--
 table/rewrite_data_files_test.go     |  6 ++--
 table/rewrite_manifests_test.go      |  6 ++--
 table/table.go                       | 26 ++++-----------
 table/transaction_assert_ref_test.go |  4 ++-
 table/transaction_internal_test.go   | 63 ++++++++++++++++++------------------
 website/src/api.md                   |  3 +-
 website/src/getting-started.md       |  5 ++-
 9 files changed, 77 insertions(+), 80 deletions(-)

diff --git a/table/branch_planning_test.go b/table/branch_planning_test.go
index cb8667ac8..35951a96d 100644
--- a/table/branch_planning_test.go
+++ b/table/branch_planning_test.go
@@ -99,7 +99,7 @@ func idRecordReader(t *testing.T, tbl *table.Table, ids 
...int64) array.RecordRe
 func appendRowsOnRef(t *testing.T, tbl *table.Table, ref string, ids ...int64) 
*table.Table {
        t.Helper()
 
-       txn, err := tbl.NewTransactionOnBranchWithError(ref)
+       txn, err := tbl.NewTransactionOnBranch(ref)
        require.NoError(t, err)
 
        rdr := idRecordReader(t, tbl, ids...)
@@ -253,7 +253,7 @@ func mainOnlyDataPath(t *testing.T, tbl *table.Table) 
string {
 func TestBranchDeleteClassifiesBranchFiles(t *testing.T) {
        tbl := seedDivergentBranch(t, newBranchPlanningTable(t, nil))
 
-       txn, err := tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
        require.NoError(t, txn.Delete(t.Context(), 
iceberg.GreaterThanEqual(iceberg.Reference("id"), int64(3)), nil))
        tbl, err = txn.Commit(t.Context())
@@ -270,7 +270,7 @@ func TestBranchDeleteClassifiesBranchFiles(t *testing.T) {
 func TestBranchDeleteRewritesPartiallyMatchedBranchFile(t *testing.T) {
        tbl := seedDivergentBranch(t, newBranchPlanningTable(t, nil))
 
-       txn, err := tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
        require.NoError(t, txn.Delete(t.Context(), 
iceberg.EqualTo(iceberg.Reference("id"), int64(3)), nil))
        tbl, err = txn.Commit(t.Context())
@@ -286,7 +286,7 @@ func TestBranchDeleteRewritesPartiallyMatchedBranchFile(t 
*testing.T) {
 func TestBranchOverwriteReplacesBranchOnlyFiles(t *testing.T) {
        tbl := seedDivergentBranch(t, newBranchPlanningTable(t, nil))
 
-       txn, err := tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
 
        rdr := idRecordReader(t, tbl, 9)
@@ -307,7 +307,7 @@ func TestOverwriteCreatingBranchPlansAgainstMainHead(t 
*testing.T) {
        tbl = appendRowsOnRef(t, tbl, table.MainBranch, 1, 2)
        require.Nil(t, tbl.SnapshotByName(branchPlanningRef), "the branch must 
not exist yet")
 
-       txn, err := tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
 
        rdr := idRecordReader(t, tbl, 9)
@@ -359,7 +359,7 @@ func TestBranchOverwriteReplaysOnBranchHeadAfterConflict(t 
*testing.T) {
        }
        writer := table.New(branchPlanningIdent, seedCat.current, metaLoc, 
branchPlanningFS, cat)
 
-       txn, err := writer.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err := writer.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
        rdr := idRecordReader(t, writer, 9)
        defer rdr.Release()
@@ -384,7 +384,7 @@ func TestBranchOverwriteReplaysOnBranchHeadAfterConflict(t 
*testing.T) {
 func TestBranchFilteredOverwriteClassifiesBranchFiles(t *testing.T) {
        tbl := seedDivergentBranch(t, newBranchPlanningTable(t, nil))
 
-       txn, err := tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
 
        rdr := idRecordReader(t, tbl, 7)
@@ -406,7 +406,7 @@ func TestBranchAddDataFilesDuplicateCheckUsesBranchHead(t 
*testing.T) {
                tbl := seedDivergentBranch(t, newBranchPlanningTable(t, nil))
                branchOnly := branchOnlyDataPath(t, tbl)
 
-               txn, err := 
tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+               txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
                require.NoError(t, err)
 
                err = txn.AddDataFiles(t.Context(), 
[]iceberg.DataFile{buildDataFile(t, branchOnly)}, nil)
@@ -418,7 +418,7 @@ func TestBranchAddDataFilesDuplicateCheckUsesBranchHead(t 
*testing.T) {
                tbl := seedDivergentBranch(t, newBranchPlanningTable(t, nil))
                mainOnly := mainOnlyDataPath(t, tbl)
 
-               txn, err := 
tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+               txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
                require.NoError(t, err)
 
                require.NoError(t, txn.AddDataFiles(t.Context(), 
[]iceberg.DataFile{buildDataFile(t, mainOnly)}, nil))
@@ -436,7 +436,7 @@ func TestBranchAddFilesDuplicateCheckUsesBranchHead(t 
*testing.T) {
                tbl := seedDivergentBranch(t, newBranchPlanningTable(t, nil))
                branchOnly := branchOnlyDataPath(t, tbl)
 
-               txn, err := 
tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+               txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
                require.NoError(t, err)
 
                err = txn.AddFiles(t.Context(), []string{branchOnly}, nil, 
false)
@@ -448,7 +448,7 @@ func TestBranchAddFilesDuplicateCheckUsesBranchHead(t 
*testing.T) {
                tbl := seedDivergentBranch(t, newBranchPlanningTable(t, nil))
                mainOnly := mainOnlyDataPath(t, tbl)
 
-               txn, err := 
tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+               txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
                require.NoError(t, err)
 
                require.NoError(t, txn.AddFiles(t.Context(), 
[]string{mainOnly}, nil, false))
@@ -476,7 +476,7 @@ func TestReplaceOnBranchOnlyTable(t *testing.T) {
                require.NoError(t, err)
                writeParquetFile(t, replacement, arrowSchema, `[{"id":8}]`)
 
-               txn, err := 
tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+               txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
                require.NoError(t, err)
                require.NoError(t, txn.ReplaceDataFilesByPath(t.Context(), 
original, []string{replacement}, nil))
                tbl, err = txn.Commit(t.Context())
@@ -490,7 +490,7 @@ func TestReplaceOnBranchOnlyTable(t *testing.T) {
                tbl := newBranchPlanningTable(t, nil)
                staged := buildDataFile(t, 
tbl.Location()+"/data/branch-1.parquet")
 
-               txn, err := 
tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+               txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
                require.NoError(t, err)
                require.NoError(t, txn.AddDataFiles(t.Context(), 
[]iceberg.DataFile{staged}, nil))
                tbl, err = txn.Commit(t.Context())
@@ -498,7 +498,7 @@ func TestReplaceOnBranchOnlyTable(t *testing.T) {
                require.Nil(t, tbl.CurrentSnapshot(), "fixture must leave main 
without a head")
 
                replacement := buildDataFile(t, 
tbl.Location()+"/data/branch-2.parquet")
-               txn, err = 
tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+               txn, err = tbl.NewTransactionOnBranch(branchPlanningRef)
                require.NoError(t, err)
                require.NoError(t, txn.ReplaceDataFiles(t.Context(),
                        []iceberg.DataFile{staged}, 
[]iceberg.DataFile{replacement}, nil))
@@ -519,14 +519,14 @@ func TestBranchReplaceFilesResolvesBranchDeleteFiles(t 
*testing.T) {
        staged := buildDataFile(t, tbl.Location()+"/data/branch-staged.parquet")
        posDelete := buildPosDeleteFile(t, 
tbl.Location()+"/data/branch-pos-delete.parquet")
 
-       txn, err := tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
        require.NoError(t, 
txn.NewRowDelta(nil).AddRows(staged).AddDeletes(posDelete).Commit(t.Context()))
        tbl, err = txn.Commit(t.Context())
        require.NoError(t, err)
 
        replacement := buildDataFile(t, 
tbl.Location()+"/data/branch-compacted.parquet")
-       txn, err = tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err = tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
        require.NoError(t, txn.ReplaceFiles(t.Context(),
                []iceberg.DataFile{staged}, []iceberg.DataFile{replacement}, 
[]iceberg.DataFile{posDelete}, nil))
@@ -553,7 +553,7 @@ func 
TestBranchMergeOnReadDeleteMergesBranchDeletionVector(t *testing.T) {
        tbl = appendRowsOnRef(t, tbl, table.MainBranch, 1, 2, 3, 4, 5)
 
        for _, id := range []int64{2, 3} {
-               txn, err := 
tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+               txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
                require.NoError(t, err)
                require.NoError(t, txn.Delete(t.Context(), 
iceberg.EqualTo(iceberg.Reference("id"), id), nil))
                tbl, err = txn.Commit(t.Context())
@@ -578,7 +578,7 @@ func TestBranchMergeOnReadDeleteTargetsBranchOnlyFile(t 
*testing.T) {
        tbl = appendRowsOnRef(t, tbl, table.MainBranch, 1, 2)
        tbl = appendRowsOnRef(t, tbl, branchPlanningRef, 3, 4)
 
-       txn, err := tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err := tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
        require.NoError(t, txn.Delete(t.Context(), 
iceberg.EqualTo(iceberg.Reference("id"), int64(3)), nil))
        tbl, err = txn.Commit(t.Context())
@@ -608,7 +608,7 @@ func TestBranchRowDeltaResolvesRemovedDeletesOnBranchHead(t 
*testing.T) {
 
        // The first vector (hiding position 1, id 2) exists only on the branch.
        dv1 := writeDV(t, location, "dv-001.puffin", dataPath, []int64{1})
-       txn, err = tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err = tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
        require.NoError(t, 
txn.NewRowDelta(nil).AddDeletes(dv1).Commit(t.Context()))
        tbl, err = txn.Commit(t.Context())
@@ -616,7 +616,7 @@ func TestBranchRowDeltaResolvesRemovedDeletesOnBranchHead(t 
*testing.T) {
        require.Equal(t, []int64{1, 3, 4, 5}, idsOnRef(t, tbl, 
branchPlanningRef))
 
        dv2 := writeDV(t, location, "dv-002.puffin", dataPath, []int64{1, 3})
-       txn, err = tbl.NewTransactionOnBranchWithError(branchPlanningRef)
+       txn, err = tbl.NewTransactionOnBranch(branchPlanningRef)
        require.NoError(t, err)
        require.NoError(t, 
txn.NewRowDelta(nil).AddDeletes(dv2).RemoveDeletes(dv1).Commit(t.Context()))
        tbl, err = txn.Commit(t.Context())
diff --git a/table/rewrite_data_files.go b/table/rewrite_data_files.go
index a66e90da2..a0d167989 100644
--- a/table/rewrite_data_files.go
+++ b/table/rewrite_data_files.go
@@ -93,7 +93,7 @@ type CompactionGroupFailure struct {
 // normally be invoked through this action so callers do not accidentally try
 // to commit the parent transaction again.
 func (t Table) RewriteDataFiles(ctx context.Context, groups 
[]CompactionTaskGroup, opts RewriteDataFilesOptions) (*RewriteResult, error) {
-       txn, err := t.NewTransactionOnBranchWithError(MainBranch)
+       txn, err := t.NewTransactionOnBranch(MainBranch)
        if err != nil {
                return nil, err
        }
@@ -692,7 +692,7 @@ func (t *Transaction) rewriteDataFilesPartial(ctx 
context.Context, groups []Comp
                }
                deletesToRemove := append(deadPositionDeletes, safeDVs...)
 
-               groupTxn, err := 
current.NewTransactionOnBranchWithError(t.branch)
+               groupTxn, err := current.NewTransactionOnBranch(t.branch)
                if err != nil {
                        return result, cleanupBatch(fmt.Errorf("create 
transaction for partial rewrite batch: %w", err))
                }
diff --git a/table/rewrite_data_files_test.go b/table/rewrite_data_files_test.go
index d9bc9dc6d..242fe6436 100644
--- a/table/rewrite_data_files_test.go
+++ b/table/rewrite_data_files_test.go
@@ -882,7 +882,7 @@ func addPartitionedRowsOnRef(t *testing.T, tbl 
*table.Table, ref, name, partitio
        info, err := os.Stat(dataPath)
        require.NoError(t, err)
 
-       txn, err := tbl.NewTransactionOnBranchWithError(ref)
+       txn, err := tbl.NewTransactionOnBranch(ref)
        require.NoError(t, err)
        builder, err := iceberg.NewDataFileBuilder(
                tbl.Spec(), iceberg.EntryContentData, dataPath, 
iceberg.ParquetFile,
@@ -927,7 +927,7 @@ func 
TestRewriteDataFiles_PartialProgressUsesTargetBranchSnapshot(t *testing.T)
                tbl.Spec(), iceberg.EntryContentPosDeletes, posDelPath, 
iceberg.ParquetFile,
                map[int]any{1000: "branch"}, nil, nil, 2, info.Size())
        require.NoError(t, err)
-       txn, err := tbl.NewTransactionOnBranchWithError(branch)
+       txn, err := tbl.NewTransactionOnBranch(branch)
        require.NoError(t, err)
        require.NoError(t, 
txn.NewRowDelta(nil).AddDeletes(delBuilder.Build()).Commit(t.Context()))
        tbl, err = txn.Commit(t.Context())
@@ -948,7 +948,7 @@ func 
TestRewriteDataFiles_PartialProgressUsesTargetBranchSnapshot(t *testing.T)
        }
        require.NotNil(t, rewriteTask.File)
 
-       txn, err = tbl.NewTransactionOnBranchWithError(branch)
+       txn, err = tbl.NewTransactionOnBranch(branch)
        require.NoError(t, err)
        result, err := txn.RewriteDataFiles(t.Context(), 
[]table.CompactionTaskGroup{{
                PartitionKey:   "branch",
diff --git a/table/rewrite_manifests_test.go b/table/rewrite_manifests_test.go
index b5b205c11..c27356870 100644
--- a/table/rewrite_manifests_test.go
+++ b/table/rewrite_manifests_test.go
@@ -425,7 +425,8 @@ func TestRewriteManifestsOnBranchOnlyTable(t *testing.T) {
                rec := array.NewRecordBatch(rewriteArrowSchema, 
[]arrow.Array{col}, 1)
                arrTbl := array.NewTableFromRecords(rewriteArrowSchema, 
[]arrow.RecordBatch{rec})
 
-               txn := tbl.NewTransactionOnBranch("feature")
+               txn, err := tbl.NewTransactionOnBranch("feature")
+               require.NoError(t, err)
                require.NoError(t, txn.AppendTable(ctx, arrTbl, 1024, nil))
                tbl, err = txn.Commit(ctx)
                require.NoError(t, err)
@@ -443,7 +444,8 @@ func TestRewriteManifestsOnBranchOnlyTable(t *testing.T) {
        require.NoError(t, err)
        require.Len(t, before, numData)
 
-       txn := tbl.NewTransactionOnBranch("feature")
+       txn, err := tbl.NewTransactionOnBranch("feature")
+       require.NoError(t, err)
        res, err := txn.RewriteManifests(ctx)
        require.NoError(t, err)
        require.False(t, res.IsNoOp(),
diff --git a/table/table.go b/table/table.go
index b2c12d29c..3807f5e7f 100644
--- a/table/table.go
+++ b/table/table.go
@@ -174,7 +174,7 @@ func (t Table) LocationProvider() (LocationProvider, error) 
{
 }
 
 func (t Table) NewTransaction() *Transaction {
-       txn, err := t.NewTransactionOnBranchWithError(MainBranch)
+       txn, err := t.NewTransactionOnBranch(MainBranch)
        if err != nil {
                return t.newBrokenTransaction(MainBranch, err)
        }
@@ -182,17 +182,6 @@ func (t Table) NewTransaction() *Transaction {
        return txn
 }
 
-// NewTransactionOnBranch creates a new transaction that commits to the named
-// branch. Use [NewTransaction] to commit to the default "main" branch.
-func (t Table) NewTransactionOnBranch(branch string) *Transaction {
-       txn, err := t.NewTransactionOnBranchWithError(branch)
-       if err != nil {
-               return t.newBrokenTransaction(branch, err)
-       }
-
-       return txn
-}
-
 func (t Table) newBrokenTransaction(branch string, err error) *Transaction {
        return &Transaction{
                tbl:     &t,
@@ -202,13 +191,12 @@ func (t Table) newBrokenTransaction(branch string, err 
error) *Transaction {
        }
 }
 
-// NewTransactionOnBranchWithError creates a new transaction and returns any 
metadata
-// initialization error that prevents builder construction.
-//
-// This preserves the old non-failing constructor contract while allowing
-// callers to receive the precise initialization error instead of hitting
-// panic/undefined behavior later.
-func (t Table) NewTransactionOnBranchWithError(branch string) (*Transaction, 
error) {
+// NewTransactionOnBranch creates a transaction that commits to the named
+// branch. Initialization failures and attempts to target a tag are returned
+// immediately instead of being stored in a broken transaction.
+// A missing branch is allowed; its absence is checked at commit time.
+// Use [NewTransaction] to target the default "main" branch.
+func (t Table) NewTransactionOnBranch(branch string) (*Transaction, error) {
        for name, ref := range t.metadata.Refs() {
                if name != branch {
                        continue
diff --git a/table/transaction_assert_ref_test.go 
b/table/transaction_assert_ref_test.go
index 47297f9f0..97b61bd98 100644
--- a/table/transaction_assert_ref_test.go
+++ b/table/transaction_assert_ref_test.go
@@ -169,7 +169,9 @@ func TestTransactionAssertRefSnapshotID(t *testing.T) {
                changed := graftSnapshotOnto(t, withFeature, "feature", 200)
                tbl, cat := newAssertRefTestTable(t, withFeature, changed)
 
-               err = commitPropsWithAssertedRef(t, 
tbl.NewTransactionOnBranch("feature"), "")
+               branchTxn, err := tbl.NewTransactionOnBranch("feature")
+               require.NoError(t, err)
+               err = commitPropsWithAssertedRef(t, branchTxn, "")
                assert.ErrorIs(t, err, ErrCommitFailed)
                assert.NotContains(t, cat.metadata.Properties(), "offsets")
        })
diff --git a/table/transaction_internal_test.go 
b/table/transaction_internal_test.go
index 0b09ed835..eec5adb36 100644
--- a/table/transaction_internal_test.go
+++ b/table/transaction_internal_test.go
@@ -157,7 +157,7 @@ func TestBranchWriteCommitsThroughCatalogPath(t *testing.T) 
{
                        // CommitTable where the branch requirement is 
validated.
                        cat := &headTrackingCatalog{metadata: divergedMeta}
                        tbl := New(ident, divergedMeta, "metadata.json", 
func(context.Context) (iceio.IO, error) { return memIO, nil }, cat)
-                       txnFeat, err := 
tbl.NewTransactionOnBranchWithError("feature")
+                       txnFeat, err := tbl.NewTransactionOnBranch("feature")
                        require.NoError(t, err)
 
                        spFeat := tc.newProd(tc.op, txnFeat, memIO, nil, nil)
@@ -218,7 +218,7 @@ func TestBranchCreateForksFromMainHead(t *testing.T) {
        // First write to the new "feature" branch.
        cat := &headTrackingCatalog{metadata: mainMeta}
        tbl := New(ident, mainMeta, "metadata.json", func(context.Context) 
(iceio.IO, error) { return memIO, nil }, cat)
-       txnFeat, err := tbl.NewTransactionOnBranchWithError("feature")
+       txnFeat, err := tbl.NewTransactionOnBranch("feature")
        require.NoError(t, err)
        spFeat := newFastAppendFilesProducer(OpAppend, txnFeat, memIO, nil, nil)
        spFeat.appendDataFile(newTestDataFile(t, spec, 
"file://feature.parquet", nil))
@@ -268,7 +268,7 @@ func TestBranchCreateForksFromMainHeadAcrossRetry(t 
*testing.T) {
        cat := &flakyCatalog{metadata: mainMeta, failUntilAttempt: 1, failWith: 
fmt.Errorf("REST: %w", ErrCommitFailed)}
        tbl := New(ident, mainMeta, "metadata.json", func(context.Context) 
(iceio.IO, error) { return memIO, nil }, cat)
 
-       txnFeat, err := tbl.NewTransactionOnBranchWithError("feature")
+       txnFeat, err := tbl.NewTransactionOnBranch("feature")
        require.NoError(t, err)
        spFeat := newFastAppendFilesProducer(OpAppend, txnFeat, memIO, nil, nil)
        spFeat.appendDataFile(newTestDataFile(t, spec, 
"file://feature.parquet", nil))
@@ -333,7 +333,7 @@ func TestBranchRetryParentsOnPeerAdvancedBranchHead(t 
*testing.T) {
        tbl := New(ident, baseMeta, "metadata.json",
                func(context.Context) (iceio.IO, error) { return wfs, nil }, 
cat)
 
-       txnFeat, err := tbl.NewTransactionOnBranchWithError("feature")
+       txnFeat, err := tbl.NewTransactionOnBranch("feature")
        require.NoError(t, err)
        spFeat := newFastAppendFilesProducer(OpAppend, txnFeat, wfs, nil, nil)
        spFeat.appendDataFile(newTestDataFile(t, spec, 
"mem://default/table-location/data/feature.parquet", nil))
@@ -359,7 +359,7 @@ func TestBranchRetryParentsOnPeerAdvancedBranchHead(t 
*testing.T) {
 
 // TestBranchCommitRejectsNameThatBecomesATagOnRetry covers the absent-branch 
to
 // tag race. "feature" does not exist when the transaction is constructed, so
-// the ref-type guard in NewTransactionOnBranchWithError has nothing to reject
+// the ref-type guard in NewTransactionOnBranch has nothing to reject
 // and the commit carries an "assert this ref is absent" requirement
 // (baseRefSnapshotID returns nil for a branch absent from the base). If a peer
 // creates that name as a TAG before the retry, the replay must fail: without
@@ -399,7 +399,7 @@ func TestBranchCommitRejectsNameThatBecomesATagOnRetry(t 
*testing.T) {
        tbl := New(ident, mainMeta, "metadata.json",
                func(context.Context) (iceio.IO, error) { return memIO, nil }, 
cat)
 
-       txnFeat, err := tbl.NewTransactionOnBranchWithError("feature")
+       txnFeat, err := tbl.NewTransactionOnBranch("feature")
        require.NoError(t, err, "the name is still absent here, so construction 
cannot reject it")
        spFeat := newFastAppendFilesProducer(OpAppend, txnFeat, memIO, nil, nil)
        spFeat.appendDataFile(newTestDataFile(t, spec, 
"file://feature.parquet", nil))
@@ -450,7 +450,7 @@ func 
TestOverwriteOnBranchOnlyTableKeepsOverwriteSemantics(t *testing.T) {
        t.Run("branch with a head overwrites", func(t *testing.T) {
                tbl := New(ident, branchOnlyMeta, "metadata.json",
                        func(context.Context) (iceio.IO, error) { return memIO, 
nil }, nil)
-               txnFeat, err := tbl.NewTransactionOnBranchWithError("feature")
+               txnFeat, err := tbl.NewTransactionOnBranch("feature")
                require.NoError(t, err)
 
                prod := txnFeat.updateSnapshot(memIO, nil, 
OpOverwrite).mergeOverwrite(nil, nil)
@@ -525,7 +525,7 @@ func TestBranchMultipleStagedSnapshotsChainOnRetry(t 
*testing.T) {
        tbl := New(ident, mainMeta, "metadata.json",
                func(context.Context) (iceio.IO, error) { return memIO, nil }, 
cat)
 
-       txnFeat, err := tbl.NewTransactionOnBranchWithError("feature")
+       txnFeat, err := tbl.NewTransactionOnBranch("feature")
        require.NoError(t, err)
 
        // A1 forks from main's head; A2 is staged on top of A1.
@@ -969,7 +969,7 @@ func 
TestTransactionApplyDedupesEquivalentRequirementsWithinAndAcrossCalls(t *te
        requireContainsRefSnapshotRequirement(t, txn.reqs, MainBranch, 
&mainSnapshotID)
 }
 
-func TestNewTransactionOnBranchWithErrorReturnsTransactionInitError(t 
*testing.T) {
+func TestNewTransactionOnBranchReportsInitializationError(t *testing.T) {
        baseMeta, err := NewMetadata(simpleSchema(), iceberg.UnpartitionedSpec, 
UnsortedSortOrder, "table-location", nil)
        require.NoError(t, err, "new metadata")
 
@@ -977,7 +977,7 @@ func 
TestNewTransactionOnBranchWithErrorReturnsTransactionInitError(t *testing.T
                Metadata: baseMeta,
        }, "metadata.json", func(context.Context) (iceio.IO, error) {
                return nil, nil
-       }, nil).NewTransactionOnBranchWithError(MainBranch)
+       }, nil).NewTransactionOnBranch(MainBranch)
        require.Error(t, err, "expected metadata builder initialization to 
fail")
        require.ErrorContains(t, err, "current schema is missing")
        require.ErrorIs(t, err, ErrInvalidMetadata)
@@ -993,14 +993,10 @@ func TestNewTransactionOnBranchRejectsTags(t *testing.T) {
        tbl := New(Identifier{"db", "table"}, meta, "metadata.json", nil, nil)
 
        before := tbl.Metadata()
-       transaction, err := tbl.NewTransactionOnBranchWithError("release")
+       transaction, err := tbl.NewTransactionOnBranch("release")
        require.ErrorIs(t, err, iceberg.ErrInvalidArgument)
        require.Nil(t, transaction)
        require.True(t, before.Equals(tbl.Metadata()))
-
-       legacyTransaction := tbl.NewTransactionOnBranch("release")
-       require.ErrorIs(t, legacyTransaction.initErr, 
iceberg.ErrInvalidArgument)
-       require.ErrorContains(t, 
legacyTransaction.SetProperties(iceberg.Properties{"k": "v"}), "tags cannot be 
transaction targets")
 }
 
 func TestTransactionCommitRejectsSameIDTagRace(t *testing.T) {
@@ -1035,13 +1031,13 @@ func 
TestNewTransactionOnBranchAllowsBranchesAndNewRefs(t *testing.T) {
        tbl := New(Identifier{"db", "table"}, meta, "metadata.json", nil, nil)
 
        for _, branch := range []string{MainBranch, "feature", "new-branch"} {
-               transaction, err := tbl.NewTransactionOnBranchWithError(branch)
+               transaction, err := tbl.NewTransactionOnBranch(branch)
                require.NoError(t, err, branch)
                require.NotNil(t, transaction, branch)
        }
 }
 
-func TestNewTransactionOnBranchKeepsLegacySignatureAndFailsOnUse(t *testing.T) 
{
+func TestNewTransactionStillDefersInitializationErrors(t *testing.T) {
        baseMeta, err := NewMetadata(simpleSchema(), iceberg.UnpartitionedSpec, 
UnsortedSortOrder, "table-location", nil)
        require.NoError(t, err, "new metadata")
 
@@ -1749,7 +1745,7 @@ func requireUntouchedRollbackRefs(t *testing.T, txn 
*Transaction, except string)
 func TestRollbackToSnapshotOnBranchDoesNotCorruptMain(t *testing.T) {
        tbl := newRollbackBranchTable(t)
 
-       branchTxn, err := tbl.NewTransactionOnBranchWithError("feature")
+       branchTxn, err := tbl.NewTransactionOnBranch("feature")
        require.NoError(t, err)
 
        require.NoError(t, branchTxn.RollbackToSnapshot(10))
@@ -1767,7 +1763,7 @@ func TestRollbackToSnapshotOnBranchDoesNotCorruptMain(t 
*testing.T) {
 func TestRollbackToSnapshotValidatesAncestryAgainstTargetBranch(t *testing.T) {
        tbl := newRollbackBranchTable(t)
 
-       branchTxn, err := tbl.NewTransactionOnBranchWithError("diverged")
+       branchTxn, err := tbl.NewTransactionOnBranch("diverged")
        require.NoError(t, err)
 
        err = branchTxn.RollbackToSnapshot(20)
@@ -1789,7 +1785,7 @@ func 
TestRollbackToSnapshotValidatesAncestryAgainstTargetBranch(t *testing.T) {
 func TestRollbackToSnapshotRejectsUnknownBranch(t *testing.T) {
        tbl := newRollbackBranchTable(t)
 
-       branchTxn, err := tbl.NewTransactionOnBranchWithError("ghost")
+       branchTxn, err := tbl.NewTransactionOnBranch("ghost")
        require.NoError(t, err)
 
        err = branchTxn.RollbackToSnapshot(10)
@@ -1808,7 +1804,7 @@ func TestRollbackToSnapshotRejectsUnknownBranch(t 
*testing.T) {
 func TestRollbackToSnapshotRejectsDanglingBranchRef(t *testing.T) {
        tbl := newRollbackBranchTable(t)
 
-       branchTxn, err := tbl.NewTransactionOnBranchWithError("feature")
+       branchTxn, err := tbl.NewTransactionOnBranch("feature")
        require.NoError(t, err)
        branchTxn.meta.refs["feature"] = SnapshotRef{SnapshotID: 9999, 
SnapshotRefType: BranchRef}
 
@@ -1827,7 +1823,7 @@ func TestRollbackToSnapshotRejectsDanglingBranchRef(t 
*testing.T) {
 func TestRollbackToSnapshotRejectsTagRef(t *testing.T) {
        tbl := newRollbackBranchTable(t)
 
-       branchTxn, err := tbl.NewTransactionOnBranchWithError("feature")
+       branchTxn, err := tbl.NewTransactionOnBranch("feature")
        require.NoError(t, err)
        branchTxn.meta.refs["feature"] = SnapshotRef{SnapshotID: 30, 
SnapshotRefType: TagRef}
 
@@ -1899,7 +1895,7 @@ func 
TestRollbackToSnapshotSharesOneBaseAssertionWithProducer(t *testing.T) {
 
        t.Run("producer then rollback", func(t *testing.T) {
                tbl := newRollbackBranchTable(t)
-               txn, err := tbl.NewTransactionOnBranchWithError("feature")
+               txn, err := tbl.NewTransactionOnBranch("feature")
                require.NoError(t, err)
 
                require.NoError(t, producerAssertion(txn))
@@ -1911,7 +1907,7 @@ func 
TestRollbackToSnapshotSharesOneBaseAssertionWithProducer(t *testing.T) {
 
        t.Run("rollback then producer", func(t *testing.T) {
                tbl := newRollbackBranchTable(t)
-               txn, err := tbl.NewTransactionOnBranchWithError("feature")
+               txn, err := tbl.NewTransactionOnBranch("feature")
                require.NoError(t, err)
 
                require.NoError(t, txn.RollbackToSnapshot(10))
@@ -1939,7 +1935,7 @@ func TestRollbackToSnapshotCommitRejectsBranchTurnedTag(t 
*testing.T) {
        raced := New(tbl.Identifier(), baseMeta, "metadata.json",
                func(context.Context) (iceio.IO, error) { return 
iceio.LocalFS{}, nil }, cat)
 
-       txn, err := raced.NewTransactionOnBranchWithError("feature")
+       txn, err := raced.NewTransactionOnBranch("feature")
        require.NoError(t, err)
        require.NoError(t, txn.RollbackToSnapshot(10))
 
@@ -2060,7 +2056,8 @@ func TestTableCommitFencesTargetBranch(t *testing.T) {
 
        t.Run("branch transaction pins only that branch", func(t *testing.T) {
                base := metadataWithRef(t, newConflictTestMetadata(t, &head), 
"audit", BranchRef)
-               tx := multiTableTestTable(t, 
base).NewTransactionOnBranch("audit")
+               tx, err := multiTableTestTable(t, 
base).NewTransactionOnBranch("audit")
+               require.NoError(t, err)
                require.NoError(t, 
tx.SetProperties(iceberg.Properties{"offsets": "42"}))
 
                tc, err := tx.TableCommit()
@@ -2075,7 +2072,8 @@ func TestTableCommitFencesTargetBranch(t *testing.T) {
 
        t.Run("absent target branch requires absence", func(t *testing.T) {
                base := newConflictTestMetadata(t, &head)
-               tx := multiTableTestTable(t, 
base).NewTransactionOnBranch("audit")
+               tx, err := multiTableTestTable(t, 
base).NewTransactionOnBranch("audit")
+               require.NoError(t, err)
                require.NoError(t, 
tx.SetProperties(iceberg.Properties{"offsets": "42"}))
 
                tc, err := tx.TableCommit()
@@ -2094,7 +2092,8 @@ func TestTableCommitFencesTargetBranch(t *testing.T) {
        // enforces snapshot-id equality alone.
        t.Run("target name created as a tag is rejected locally", func(t 
*testing.T) {
                base := newConflictTestMetadata(t, &head)
-               tx := multiTableTestTable(t, 
base).NewTransactionOnBranch("audit")
+               tx, err := multiTableTestTable(t, 
base).NewTransactionOnBranch("audit")
+               require.NoError(t, err)
                require.NoError(t, 
tx.SetProperties(iceberg.Properties{"offsets": "42"}))
 
                tc, err := tx.TableCommit()
@@ -2147,13 +2146,15 @@ func TestTableCommitRequirementsMatchCommit(t 
*testing.T) {
                        require.Equal(t, base, committed.Metadata())
                        require.Equal(t, base, payload.Metadata())
 
-                       txCommit := committed.NewTransactionOnBranch(branch)
+                       txCommit, err := 
committed.NewTransactionOnBranch(branch)
+                       require.NoError(t, err)
                        require.NoError(t, 
txCommit.SetProperties(iceberg.Properties{"offsets": "42"}))
-                       _, err := txCommit.Commit(t.Context())
+                       _, err = txCommit.Commit(t.Context())
                        require.NoError(t, err)
                        require.Len(t, cat.reqs, 1)
 
-                       txPayload := payload.NewTransactionOnBranch(branch)
+                       txPayload, err := payload.NewTransactionOnBranch(branch)
+                       require.NoError(t, err)
                        require.NoError(t, 
txPayload.SetProperties(iceberg.Properties{"offsets": "42"}))
                        tc, err := txPayload.TableCommit()
                        require.NoError(t, err)
diff --git a/website/src/api.md b/website/src/api.md
index f8df5d69d..85504ee5a 100644
--- a/website/src/api.md
+++ b/website/src/api.md
@@ -388,7 +388,8 @@ newTbl, err := txn.Commit(ctx)
 To target a specific branch:
 
 ```go
-txn := tbl.NewTransactionOnBranch("staging")
+txn, err := tbl.NewTransactionOnBranch("staging")
+if err != nil { /* ... */ }
 ```
 
 `Commit` retries automatically on conflict (`ErrCommitFailed`) - tune via the 
`commit.retry.*` table properties.
diff --git a/website/src/getting-started.md b/website/src/getting-started.md
index fc871da84..3ef644477 100644
--- a/website/src/getting-started.md
+++ b/website/src/getting-started.md
@@ -235,7 +235,10 @@ func createExperimentBranch(ctx context.Context, cat 
*sqlcat.Catalog, tbl *table
 
 // Step 2: open a transaction on the branch and write.
 func writeOnBranch(ctx context.Context, tbl *table.Table, arrowTbl 
arrow.Table) (*table.Table, error) {
-    txn := tbl.NewTransactionOnBranch("experiment")
+    txn, err := tbl.NewTransactionOnBranch("experiment")
+    if err != nil {
+        return nil, err
+    }
     if err := txn.AppendTable(ctx, arrowTbl, 1024, nil); err != nil {
         return nil, err
     }

Reply via email to