kubernetes/kops · error

error fetching %q: %v

Error message

error fetching %q: %v

What it means

readHTTPLocation issues a GET via http.DefaultClient (with backoff retries). If the transport itself fails - DNS failure, connection refused/reset, TLS error, timeout - the network error is wrapped as 'error fetching <url>'. The retry loop retries this condition up to the backoff step count before returning.

Source

Thrown at util/pkg/vfs/context.go:268

// It will retry a few times on a 500 class error
func (c *VFSContext) readHTTPLocation(httpURL string, httpHeaders map[string]string, opts vfsOptions) ([]byte, error) {
	var body []byte

	done, err := RetryWithBackoff(opts.backoff, func() (bool, error) {
		klog.V(4).Infof("Performing HTTP request: GET %s", httpURL)
		req, err := http.NewRequest("GET", httpURL, nil)
		if err != nil {
			return false, err
		}
		for k, v := range httpHeaders {
			req.Header.Add(k, v)
		}
		response, err := http.DefaultClient.Do(req)
		if response != nil {
			defer response.Body.Close()
		}
		if err != nil {
			return false, fmt.Errorf("error fetching %q: %v", httpURL, err)
		}
		body, err = io.ReadAll(response.Body)
		if err != nil {
			return false, fmt.Errorf("error reading response for %q: %v", httpURL, err)
		}
		if response.StatusCode == 404 {
			// We retry on 404s in case of eventual consistency
			return false, os.ErrNotExist
		}
		if response.StatusCode >= 500 && response.StatusCode <= 599 {
			// Retry on 5XX errors
			return false, fmt.Errorf("unexpected response code %q for %q: %v", response.Status, httpURL, string(body))
		}

		if response.StatusCode == 200 {
			return true, nil
		}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check reachability: `curl -v <url>` from the same host to see the underlying transport error
  2. Fix DNS/hostname or use the correct IP/endpoint
  3. Configure proxy env vars (HTTP_PROXY/HTTPS_PROXY) if egress requires a proxy
  4. Fix TLS trust (install CA) if the error is a certificate failure
  5. Increase the backoff (WithBackoff option) for slow/flaky endpoints

Example fix

// before
// no proxy set, fetch fails behind corporate firewall
resp, err := vfs.Context.ReadFile("https://addons.example.org/addons.yaml")
// after
os.Setenv("HTTPS_PROXY", "http://proxy.corp:3128")
resp, err := vfs.Context.ReadFile("https://addons.example.org/addons.yaml", vfs.WithBackoff(wait.Backoff{Duration: time.Second, Factor: 2, Steps: 8}))
Defensive patterns

Strategy: retry

Validate before calling

func urlReachable(rawURL string) error {
	u, err := url.Parse(rawURL)
	if err != nil {
		return err
	}
	if u.Scheme != "http" && u.Scheme != "https" {
		return fmt.Errorf("unexpected scheme %q", u.Scheme)
	}
	return nil // reachability itself can only be probed by attempting the fetch
}

Type guard

func isFetchableURL(rawURL string) bool {
	u, err := url.Parse(rawURL)
	return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}

Try / catch

err := wait.ExponentialBackoff(wait.Backoff{Duration: time.Second, Factor: 2, Steps: 5}, func() (bool, error) {
	_, err := vfs.Context.ReadFile(loc)
	if err != nil && strings.Contains(err.Error(), "error fetching") {
		return false, nil // transient transport failure - retry
	}
	return err == nil, err
})

Prevention

When it happens

Trigger: ReadFile with http(s):// or metadata://gce|digitalocean|openstack URLs when the server is down/unreachable, DNS fails, TLS handshake fails, or the request times out; also any http.NewRequest-level failure reaching Do.

Common situations: Wrong hostname/port in a channel or addon URL; corporate proxy required but not configured (HTTP_PROXY unset); IMDS endpoint blocked; TLS interception with an untrusted CA; server temporarily down while the 5-step backoff exhausts.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/afe498bc84ef7f35. Report an issue: GitHub.