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
- Inspect the wrapped error (%w) to identify the root cause (connection reset, context deadline, etc.)
- Retry the metadata request; body-read failures are typically transient
- Check for proxies or middleboxes between the host and the metadata endpoint
- Increase or verify the HTTP client timeout / context deadline is not too tight
- 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
- Set a sane client timeout and retry idempotent metadata GETs
- Wrap the body in io.LimitReader to avoid unbounded reads
- Log the wrapped cause to distinguish transient resets from deadline expiry
- Treat body-read errors as retryable, unlike parse errors
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
- droplet metadata returned non-200 status code: %d
- failed to read metadata information %s: %v
- instance %s from Akamai (Linode) metadata was empty
- error reading response for %q: %v
- error building linode node identifier: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/f47cf922384a9380.
Report an issue: GitHub.