kubernetes/kops · error

reading instance metadata response: %w

Error message

reading instance metadata response: %w

What it means

getLinodeMetadataValue fetches instance metadata from the Akamai (Linode) metadata service. After the HTTP request succeeds with status 200, it reads the response body with io.ReadAll; if that read fails (connection reset mid-body, truncated chunked transfer, context cancellation), the error is wrapped with this message. It signals the metadata HTTP exchange broke while downloading the payload, not that the payload was invalid.

Source

Thrown at upup/pkg/fi/cloudup/linode/linodemetadata/authenticator.go:120

	instanceReq, err := http.NewRequestWithContext(ctx, http.MethodGet, metadataBaseURL+"/v1/instance", nil)
	if err != nil {
		return "", fmt.Errorf("building instance metadata request: %w", err)
	}
	instanceReq.Header.Set("Metadata-Token", token)

	instanceResp, err := client.Do(instanceReq)
	if err != nil {
		return "", fmt.Errorf("fetching instance metadata: %w", err)
	}
	defer instanceResp.Body.Close()

	if instanceResp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("fetching instance metadata: unexpected status code %d", instanceResp.StatusCode)
	}

	instanceBytes, err := io.ReadAll(instanceResp.Body)
	if err != nil {
		return "", fmt.Errorf("reading instance metadata response: %w", err)
	}

	value := parseLinodeMetadataValue(string(instanceBytes), key)
	if value == "" {
		return "", fmt.Errorf("instance %s from Akamai (Linode) metadata was empty", key)
	}
	return value, nil
}

// parseLinodeMetadataValue parses the Akamai (Linode) metadata response for the given key
// and returns the value as a string.
func parseLinodeMetadataValue(metadata string, key string) string {
	prefix := key + ":"
	for _, line := range strings.Split(metadata, "\n") {
		line = strings.TrimSpace(line)
		if !strings.HasPrefix(line, prefix) {
			continue
		}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Inspect the wrapped error (%w) to identify the root cause (connection reset, context deadline, etc.)
  2. Retry the metadata request; body-read failures are typically transient
  3. Check for proxies or middleboxes between the host and the metadata endpoint
  4. Increase or verify the HTTP client timeout / context deadline is not too tight
  5. Run the request against a known-good metadata endpoint to rule out server-side truncation

Example fix

// before
instanceBytes, err := io.ReadAll(instanceResp.Body)
if err != nil {
	return "", fmt.Errorf("reading instance metadata response: %w", err)
}
// after
instanceBytes, err := io.ReadAll(io.LimitReader(instanceResp.Body, maxMetadataSize))
if err != nil {
	return "", fmt.Errorf("reading instance metadata response: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

if instanceResp.Body == nil { return errors.New("metadata response has no body") }

Try / catch

bytes, err := io.ReadAll(resp.Body)
if err != nil {
	return retryable(fmt.Errorf("reading instance metadata response: %w", err))
}

Prevention

When it happens

Trigger: io.ReadAll(instanceResp.Body) returns a non-nil err after a 200 status: the metadata server closes the connection mid-response, the chunked body is truncated, a request deadline/context expires during the read, or a proxy intercepts and drops the stream.

Common situations: Flaky network or overloaded metadata endpoint on a Linode host; a local test httptest server that closes the connection without writing a full body; TLS interception proxies killing long-lived keep-alive connections; callers cancelling the request context mid-read.

Related errors


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