{"record":{"id":"38c0471d8b3c8ee1","repo":"JuliusBrussee/caveman","slug":"kms-read-s-response-w","errorCode":null,"errorMessage":"kms: read %s response: %w","messagePattern":"kms: read (.+?) response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/kms/kms.go","lineNumber":371,"sourceCode":"\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: create %s request: %w\", operation, err)\n\t}\n\treq.Header.Set(\"content-type\", \"application/json\")\n\treq.Header.Set(\"accept\", \"application/json\")\n\treq.Header.Set(\"x-auth-token\", c.token)\n\tresp, err := c.httpClient.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: %s request failed: %w\", operation, err)\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\t_, _ = io.Copy(io.Discard, io.LimitReader(resp.Body, 32<<10))\n\t\treturn fmt.Errorf(\"kms: %s returned HTTP %d\", operation, resp.StatusCode)\n\t}\n\tdata, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseBytes+1))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"kms: read %s response: %w\", operation, err)\n\t}\n\tif len(data) > maxResponseBytes {\n\t\treturn fmt.Errorf(\"kms: %s response exceeds limit\", operation)\n\t}\n\tif err := json.Unmarshal(data, output); err != nil {\n\t\treturn fmt.Errorf(\"kms: decode %s response: %w\", operation, err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":353,"sourceCodeEnd":381,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/kms/kms.go#L353-L381","documentation":"The KMS response was received with HTTP 200, but reading the response body via io.ReadAll failed (connection reset mid-body, context cancellation, unexpected EOF). The client wraps the read error with the operation name. The request succeeded at the HTTP level but the full body could not be consumed.","triggerScenarios":"Encrypt or Decrypt calls where the server closes the connection while the body is streaming, the request context is cancelled mid-read, LB idle timeout truncating the response, or transient socket errors during body transfer.","commonSituations":"Large ciphertext/large responses over flaky links, reverse proxies with short read timeouts, pod/network interruption in Kubernetes during the response, or keep-alive connections killed by an intermediary.","solutions":["Retry the operation with exponential backoff — this is typically transient.","Check intermediary proxies/load balancers for response idle/read timeout settings.","Inspect the wrapped cause for context cancellation; ensure the caller's ctx isn't being cancelled prematurely.","Increase keep-alive robustness (Transport settings) or disable connection reuse if an intermediary is killing idle connections.","Check server-side logs for the request to confirm the server finished writing the response."],"exampleFix":"// before\nout, err := kms.Decrypt(ctx, ct) // kms: read Decrypt response: unexpected EOF\n// after\nvar out DecryptOutput\nerr := retry.Do(3, backoff, func() error {\n    var e error\n    out, e = kms.Decrypt(ctx, ct)\n    return e\n})","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.HasPrefix(err.Error(), \"kms: read \") {\n    var netErr net.Error\n    if errors.As(err, &netErr) && netErr.Timeout() {\n        // retry with backoff\n    }\n    return fmt.Errorf(\"reading KMS response: %w\", err)\n}","preventionTips":["Wrap KMS calls in bounded retries with exponential backoff.","Check proxy/LB idle-timeout settings against worst-case response times.","Avoid cancelling the request context prematurely on large payloads.","Monitor for connection resets between client and KMS."],"tags":["network","http","kms","io","go"],"backgroundTag":"network-request-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}