#10424·pipeline

Bundle resolver does not retry on network-level transient errors (TCP timeout, connection reset, EOF)

Author: gbenhaimCreated Jul 14, 2026Updated Sep 2, 2026
Labelskind/featurehelp wanted

Problem

The bundle resolver's retry/backoff mechanism (configured via bundleresolver-config) only retries on HTTP response codes (429, 5xx). It does not retry on network-level transient errors such as:

  • TCP connection timeouts (dial tcp ... i/o timeout)
  • Connection resets (connection reset by peer)
  • Broken pipes (broken pipe)
  • EOF errors (server closed connection mid-transfer)
  • TLS handshake timeouts

These are all recoverable, transient errors that occur frequently in production environments with shared egress proxies, registry mirrors behind load balancers, or cloud NAT gateways with connection limits.

Root Cause

The retry logic in go-containerregistry's transport.Retry relies on net.Error.Temporary() to identify retryable network errors. However, Go deprecated Temporary() (it returns false for most errors since Go 1.18+), so network-level errors are no longer classified as retryable.

The Timeout() check and connection-reset detection were added in newer go-containerregistry versions, but may not be present in the version bundled with current Tekton releases.

Observed Behavior

With bundleresolver-config set to:

yaml
backoff-duration: "15s"
backoff-factor: "2.0"
backoff-steps: "10"
backoff-cap: "15m"
fetch-timeout: "2m"

A bundle reference pointing to a host that causes a TCP timeout fails immediately after the first dial timeout (~30s) with no retry:

cannot retrieve the oci image: Get "https://...": dial tcp ...: i/o timeout

In contrast, if the registry returns HTTP 503, the backoff configuration would be respected.

Expected Behavior

Network-level transient errors should be retried with the same backoff configuration as HTTP 5xx responses. At minimum:

  • Timeout() errors (connection timeouts, read timeouts)
  • ECONNRESET / connection reset by peer
  • EPIPE / broken pipe
  • Unexpected EOF

Suggested Fix

Either:

  1. In go-containerregistry: Update transport.Retry's shouldRetry to check Timeout() and recognize connection-reset/EOF errors as retryable (some newer versions may already do this).
  2. In Tekton resolvers: Add a resolver-level retry loop that re-attempts the full resolution on any error (not just HTTP-level errors), using the configured backoff parameters.

Related

  • #8571 — Retry failed resolvers (general retry support for all resolvers)

-- Gal's Cursor