#11991·temporal

ExponentialRetryPolicy without maximum interval returns a ~292-year backoff on arm64 when the interval overflows

Author: harrisleeshCreated Sep 10, 2026Updated Sep 10, 2026

What are you really trying to do?

Use backoff.NewExponentialRetryPolicy (the Retrier path in common/backoff/retrypolicy.go) with the maximum interval cleared (NoInterval) and rely on the documented behavior that retries stop when the computed interval overflows.

Describe the bug

nextInterval is computed as float64; with maximumInterval == NoInterval and expirationInterval == NoInterval it can exceed MaxInt64 nanoseconds, and Go's conversion of an out-of-range float64 to time.Duration is platform-dependent:

  • amd64: wraps negative, which is accidentally caught by the nextDuration < p.initialInterval check and returns done — matching the code comment ("Disallow retries ... if nextInterval overflows").
  • arm64: saturates to MaxInt64, so NextBackOff returns 2562047h47m16.8s (~292 years) and the retrier effectively waits forever.

This is the same bug class as #11225 fixed for ExponentialBackoffAlgorithm in common/backoff/retry.go; the Retrier/retrypolicy.go path never received that fix. Severity is honestly latent: no in-tree production caller currently clears the maximum interval, but the API allows it and behavior silently diverges by architecture.

Minimal Reproduction

On arm64, a unit test driving an uncapped policy past the overflow point expects done (-1ns) and observes 2562047h47m16.854775807s on main (706e0b4).

Environment/Versions

  • Temporal Version: main (706e0b4)
  • darwin/arm64 (bug manifests on arm64; amd64 accidentally behaves as documented)

I will submit a PR that explicitly returns done when the computed interval reaches MaxInt64, making both platforms follow the documented intent; capped policies are unaffected.