This is an automated email from the ASF dual-hosted git repository.
github-actions[bot] pushed a commit to branch gh-pages
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git
The following commit(s) were added to refs/heads/gh-pages by this push:
new d7fe87283 deploy: e904fb445780226acf43812afe78c1bd6ea6c80c
d7fe87283 is described below
commit d7fe87283b37939ce414e22ea166c6e6896f8398
Author: zeroshade <[email protected]>
AuthorDate: Tue Oct 27 20:57:02 2026 +0000
deploy: e904fb445780226acf43812afe78c1bd6ea6c80c
---
api.html | 2 +-
concurrent-writes.html | 27 ++++++++++++++++++++++++++-
print.html | 29 +++++++++++++++++++++++++++--
searchindex.js | 2 +-
searchindex.json | 2 +-
5 files changed, 56 insertions(+), 6 deletions(-)
diff --git a/api.html b/api.html
index d25ee987e..4d5927210 100644
--- a/api.html
+++ b/api.html
@@ -515,7 +515,7 @@ newTbl, err := txn.Commit(ctx)
<pre><code class="language-go">txn, err :=
tbl.NewTransactionOnBranch("staging")
if err != nil { /* ... */ }
</code></pre>
-<p><code>Commit</code> retries automatically on conflict
(<code>ErrCommitFailed</code>) - tune via the <code>commit.retry.*</code> table
properties.</p>
+<p><code>Commit</code> can retry on conflict (<code>ErrCommitFailed</code>)
when <code>commit.retry.num-retries</code> is set. See <a
href="./concurrent-writes.html#automatic-retry">Automatic retry</a> for the
<code>commit.retry.*</code> table properties.</p>
<h2 id="schema-and-partition-evolution"><a class="header"
href="#schema-and-partition-evolution">Schema and partition evolution</a></h2>
<h3 id="schema-evolution"><a class="header" href="#schema-evolution">Schema
evolution</a></h3>
<pre><code class="language-go">import
"github.com/apache/iceberg-go/table"
diff --git a/concurrent-writes.html b/concurrent-writes.html
index 1252a5dd3..2c2db7668 100644
--- a/concurrent-writes.html
+++ b/concurrent-writes.html
@@ -247,6 +247,9 @@ state. A failed validation surfaces as one of:</p>
retried after refreshing (see below).</li>
<li><code>table.ErrCommitDiverged</code> — terminal. The base snapshot is no
longer on the
branch at all, so a retry cannot reconcile the change.</li>
+<li><code>table.ErrTransactionUnusable</code> — this transaction can't be
committed again.
+If the error also matches <code>ErrCommitFailed</code>, retry in a new
transaction from a
+reloaded table.</li>
</ul>
<pre><code class="language-go">import (
"context"
@@ -257,7 +260,9 @@ branch at all, so a retry cannot reconcile the change.</li>
_, err := txn.Commit(context.Background())
switch {
-case errors.Is(err, table.ErrCommitDiverged):
+case errors.Is(err, table.ErrTransactionUnusable) && errors.Is(err,
table.ErrCommitFailed):
+ // a concurrent change: retry in a new transaction from a reloaded table
+case errors.Is(err, table.ErrCommitDiverged), errors.Is(err,
table.ErrTransactionUnusable):
// unrecoverable: rebuild the operation from the latest table
case errors.Is(err, table.ErrCommitFailed):
// retriable: refresh and try again (the retry loop does this for you)
@@ -298,6 +303,26 @@ _, err := cat.CreateTable(ctx, ident, schema,
commit conflicts, including requirements that fail because of a concurrent
change, as <code>ErrCommitFailed</code>, so the retry loop engages on all of
them.</p>
</blockquote>
+<p>Only the implicit assertion on the commit branch's head is rebased after a
+refresh. Other requirements, including the schema, spec, sort order, and pinned
+refs, must still hold. Otherwise, the commit fails without another attempt and
+the transaction is unusable.</p>
+<p>After a conflict, calling <code>Commit</code> again on the same transaction
refreshes the
+table and replays the staged changes like the next retry attempt, so it can
+rebase onto a peer's commit even with retries disabled. Each call gets the
+configured retry budget. A commit carrying delete-file removals that cannot be
+replayed resubmits only if its branch has not moved. The rejections after a
+refresh that make the transaction unusable are listed on
+<code>ErrTransactionUnusable</code>.</p>
+<p>A failed commit keeps the files it staged until a later commit lands. A
+transaction you abandon leaves them for orphan file removal, as one with
+retries disabled always has. An abandoned manifest rewrite also leaves the
+manifests that later attempts merged. <code>TableCommit</code> refuses a
transaction whose
+commit failed, since the multi-table path does not refresh. Call
<code>Commit</code> to
+resume it, or build a new transaction.</p>
+<p>Because an <code>ExpireSnapshots</code> that removes something pins the
commit branch, a
+transaction that also appends fails instead of rebasing onto a peer's append.
+This is deliberate, since the expiry was computed from the old head.</p>
</main>
diff --git a/print.html b/print.html
index 3dd72abe2..f0c4e582e 100644
--- a/print.html
+++ b/print.html
@@ -1477,7 +1477,7 @@ newTbl, err := txn.Commit(ctx)
<pre><code class="language-go">txn, err :=
tbl.NewTransactionOnBranch("staging")
if err != nil { /* ... */ }
</code></pre>
-<p><code>Commit</code> retries automatically on conflict
(<code>ErrCommitFailed</code>) - tune via the <code>commit.retry.*</code> table
properties.</p>
+<p><code>Commit</code> can retry on conflict (<code>ErrCommitFailed</code>)
when <code>commit.retry.num-retries</code> is set. See <a
href="./concurrent-writes.html#automatic-retry">Automatic retry</a> for the
<code>commit.retry.*</code> table properties.</p>
<h2 id="schema-and-partition-evolution"><a class="header"
href="#schema-and-partition-evolution">Schema and partition evolution</a></h2>
<h3 id="schema-evolution"><a class="header" href="#schema-evolution">Schema
evolution</a></h3>
<pre><code class="language-go">import
"github.com/apache/iceberg-go/table"
@@ -1987,6 +1987,9 @@ state. A failed validation surfaces as one of:</p>
retried after refreshing (see below).</li>
<li><code>table.ErrCommitDiverged</code> — terminal. The base snapshot is no
longer on the
branch at all, so a retry cannot reconcile the change.</li>
+<li><code>table.ErrTransactionUnusable</code> — this transaction can't be
committed again.
+If the error also matches <code>ErrCommitFailed</code>, retry in a new
transaction from a
+reloaded table.</li>
</ul>
<pre><code class="language-go">import (
"context"
@@ -1997,7 +2000,9 @@ branch at all, so a retry cannot reconcile the
change.</li>
_, err := txn.Commit(context.Background())
switch {
-case errors.Is(err, table.ErrCommitDiverged):
+case errors.Is(err, table.ErrTransactionUnusable) && errors.Is(err,
table.ErrCommitFailed):
+ // a concurrent change: retry in a new transaction from a reloaded table
+case errors.Is(err, table.ErrCommitDiverged), errors.Is(err,
table.ErrTransactionUnusable):
// unrecoverable: rebuild the operation from the latest table
case errors.Is(err, table.ErrCommitFailed):
// retriable: refresh and try again (the retry loop does this for you)
@@ -2038,6 +2043,26 @@ _, err := cat.CreateTable(ctx, ident, schema,
commit conflicts, including requirements that fail because of a concurrent
change, as <code>ErrCommitFailed</code>, so the retry loop engages on all of
them.</p>
</blockquote>
+<p>Only the implicit assertion on the commit branch's head is rebased after a
+refresh. Other requirements, including the schema, spec, sort order, and pinned
+refs, must still hold. Otherwise, the commit fails without another attempt and
+the transaction is unusable.</p>
+<p>After a conflict, calling <code>Commit</code> again on the same transaction
refreshes the
+table and replays the staged changes like the next retry attempt, so it can
+rebase onto a peer's commit even with retries disabled. Each call gets the
+configured retry budget. A commit carrying delete-file removals that cannot be
+replayed resubmits only if its branch has not moved. The rejections after a
+refresh that make the transaction unusable are listed on
+<code>ErrTransactionUnusable</code>.</p>
+<p>A failed commit keeps the files it staged until a later commit lands. A
+transaction you abandon leaves them for orphan file removal, as one with
+retries disabled always has. An abandoned manifest rewrite also leaves the
+manifests that later attempts merged. <code>TableCommit</code> refuses a
transaction whose
+commit failed, since the multi-table path does not refresh. Call
<code>Commit</code> to
+resume it, or build a new transaction.</p>
+<p>Because an <code>ExpireSnapshots</code> that removes something pins the
commit branch, a
+transaction that also appends fails instead of rebasing onto a peer's append.
+This is deliberate, since the expiry was computed from the old head.</p>
<div style="break-before: page; page-break-before: always;"></div><!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
diff --git a/searchindex.js b/searchindex.js
index 481f7bfb2..3af9c088e 100644
--- a/searchindex.js
+++ b/searchindex.js
@@ -1 +1 @@
-Object.assign(window.search,
{"doc_urls":["introduction.html#iceberg-go","introduction.html#where-to-start","introduction.html#what-works-today","introduction.html#beyond-go","introduction.html#help-and-contribution","install.html#install","install.html#requirements","install.html#installation","getting-started.html#getting-started","getting-started.html#1-install","getting-started.html#2-open-a-local-catalog","getting-started.html#3-create-a-namespace-and-a-table","getting-started.html#
[...]
\ No newline at end of file
+Object.assign(window.search,
{"doc_urls":["introduction.html#iceberg-go","introduction.html#where-to-start","introduction.html#what-works-today","introduction.html#beyond-go","introduction.html#help-and-contribution","install.html#install","install.html#requirements","install.html#installation","getting-started.html#getting-started","getting-started.html#1-install","getting-started.html#2-open-a-local-catalog","getting-started.html#3-create-a-namespace-and-a-table","getting-started.html#
[...]
\ No newline at end of file
diff --git a/searchindex.json b/searchindex.json
index 95891f531..18ca71807 100644
--- a/searchindex.json
+++ b/searchindex.json
@@ -1 +1 @@
-{"doc_urls":["introduction.html#iceberg-go","introduction.html#where-to-start","introduction.html#what-works-today","introduction.html#beyond-go","introduction.html#help-and-contribution","install.html#install","install.html#requirements","install.html#installation","getting-started.html#getting-started","getting-started.html#1-install","getting-started.html#2-open-a-local-catalog","getting-started.html#3-create-a-namespace-and-a-table","getting-started.html#4-write-some-arrow-data","get
[...]
\ No newline at end of file
+{"doc_urls":["introduction.html#iceberg-go","introduction.html#where-to-start","introduction.html#what-works-today","introduction.html#beyond-go","introduction.html#help-and-contribution","install.html#install","install.html#requirements","install.html#installation","getting-started.html#getting-started","getting-started.html#1-install","getting-started.html#2-open-a-local-catalog","getting-started.html#3-create-a-namespace-and-a-table","getting-started.html#4-write-some-arrow-data","get
[...]
\ No newline at end of file