From 7a574b03977fca246399b9304096ba2fd8ff5ba1 Mon Sep 17 00:00:00 2001 From: tlplayer Date: Fri, 10 Jul 2026 09:13:10 -0400 Subject: [PATCH] client-go: preserve context cancellation in retry OnError OnError replaced context cancellation errors with a nil lastErr when the error was non-retriable. Preserve the callback error when no retriable error was recorded. Add a regression test covering a context cancellation returned on the first invocation. Kubernetes-commit: 23b344cd1581a871984e44be951249af6018242e --- util/retry/util.go | 2 +- util/retry/util_test.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/util/retry/util.go b/util/retry/util.go index 57d3cd49c..fd2a959ec 100644 --- a/util/retry/util.go +++ b/util/retry/util.go @@ -59,7 +59,7 @@ func OnError(backoff wait.Backoff, retriable func(error) bool, fn func() error) return false, err } }) - if wait.Interrupted(err) { + if wait.Interrupted(err) && lastErr != nil { err = lastErr } return err diff --git a/util/retry/util_test.go b/util/retry/util_test.go index dbb4374fe..76529fdf9 100644 --- a/util/retry/util_test.go +++ b/util/retry/util_test.go @@ -17,6 +17,8 @@ limitations under the License. package retry import ( + "context" + stderrors "errors" "fmt" "testing" @@ -69,3 +71,12 @@ func TestRetryOnConflict(t *testing.T) { t.Errorf("unexpected error: %v", err) } } + +func TestRetryOnConflictPreservesContextErrorWithoutLastError(t *testing.T) { + err := RetryOnConflict(DefaultBackoff, func() error { + return context.Canceled + }) + if !stderrors.Is(err, context.Canceled) { + t.Fatalf("expected context.Canceled, got %v", err) + } +}