kubernetes/kops · error
reading intermediate certificate from %s: %w
Error message
reading intermediate certificate from %s: %w
What it means
After a successful HTTP 200 response, fetchCertificate reads the body with io.ReadAll wrapped in a LimitReader sized to intermediateCertMaxResponseBytes plus one byte. If the read itself fails mid-stream (connection reset, truncated response, timeout), this error wraps the underlying I/O error together with the URL.
Source
Thrown at upup/pkg/fi/cloudup/azure/attest.go:444
}
// fetchCertificate fetches and parses a DER-encoded certificate from the given URL.
func fetchCertificate(client *http.Client, url string) (*x509.Certificate, error) {
resp, err := client.Get(url)
if err != nil {
return nil, fmt.Errorf("fetching intermediate certificate from %s: %w", url, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("fetching intermediate certificate from %s: status %d", url, resp.StatusCode)
}
// Cap the body read to reject pathologically large responses. Read one extra byte so we can
// distinguish "at the limit" from "exceeded limit".
body, err := io.ReadAll(io.LimitReader(resp.Body, intermediateCertMaxResponseBytes+1))
if err != nil {
return nil, fmt.Errorf("reading intermediate certificate from %s: %w", url, err)
}
if len(body) > intermediateCertMaxResponseBytes {
return nil, fmt.Errorf("intermediate certificate from %s exceeds %d bytes", url, intermediateCertMaxResponseBytes)
}
cert, err := x509.ParseCertificate(body)
if err != nil {
return nil, fmt.Errorf("parsing intermediate certificate from %s: %w", url, err)
}
return cert, nil
}
// validateFetchedIntermediateForSigner checks that a fetched intermediate is actually the issuer
// referenced by the signer certificate before it is used or cached. This is a structural check
// only; the cryptographic signature is verified later by verifySignerCertChain.
func validateFetchedIntermediateForSigner(signer *x509.Certificate, cert *x509.Certificate) error {
if signer == nil {
return fmt.Errorf("signer certificate is required")View on GitHub (pinned to 4c8573c808)
Solutions
- Retry the fetch; transient truncation usually succeeds on a second attempt
- Bypass or fix the proxy/LB that is terminating the connection early
- Increase HTTP client timeouts so slow responses are not cut off mid-read
Example fix
// before
client := &http.Client{} // default: short/no body-read tolerance, may abort mid-stream
// after
client := &http.Client{Timeout: 30 * time.Second}
// plus retry on io.ErrUnexpectedEOF before failing the chain build Defensive patterns
Strategy: retry
Validate before calling
// Use a client with sane timeouts so reads are not cut off silently
client := &http.Client{Timeout: 30 * time.Second} Try / catch
_, err := fetchCertificate(client, url)
if err != nil && (errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.DeadlineExceeded)) {
cert, err = fetchCertificate(client, url) // single retry on truncated reads
} Prevention
- Set explicit HTTP client timeouts
- Avoid proxies that close keep-alive connections mid-transfer
- Retry idempotent GETs once or twice on I/O errors
When it happens
Trigger: The response body read aborts before EOF while downloading an intermediate certificate — server closed the connection early, TLS truncation, or an intermediate network device dropped the stream.
Common situations: Flaky proxies/LBs closing keep-alive connections; very constrained networks with aggressive idle timeouts; CA endpoint under load aborting the transfer.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- fetching intermediate certificate from %s: %w
- intermediate certificate fetch recently failed for signer is
- fetching intermediate certificate from %s: status %d
- intermediate certificate from %s exceeds %d bytes
- parsing intermediate certificate from %s: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/cd14f0102c9af613.
Report an issue: GitHub.