{"record":{"id":"9cc275e96c1ee728","repo":"OpenFeign/feign","slug":"s-reading-s-s-9cc275","errorCode":null,"errorMessage":"%s reading %s %s","messagePattern":"(.+?) reading (.+?) (.+?)","errorType":"exception","errorClass":"FeignException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/feign/ResponseHandler.java","lineNumber":83,"sourceCode":"  public Object handleResponse(\n      String configKey, Response response, Type returnType, long elapsedTime) throws Exception {\n    try {\n      response = logAndRebufferResponseIfNeeded(configKey, response, elapsedTime);\n      return executionChain.next(\n          new InvocationContext(\n              configKey,\n              decoder,\n              errorDecoder,\n              dismiss404,\n              closeAfterDecode,\n              decodeVoid,\n              response,\n              returnType));\n    } catch (final IOException e) {\n      if (logLevel != Level.NONE) {\n        logger.logIOException(configKey, logLevel, e, elapsedTime);\n      }\n      throw errorReading(response.request(), response, e);\n    } catch (Exception e) {\n      ensureClosed(response.body());\n      throw e;\n    }\n  }\n\n  private Response logAndRebufferResponseIfNeeded(\n      String configKey, Response response, long elapsedTime) throws IOException {\n    if (logLevel == Level.NONE) {\n      return response;\n    }\n\n    return logger.logAndRebufferResponse(configKey, logLevel, response, elapsedTime);\n  }\n}\n","sourceCodeStart":65,"sourceCodeEnd":99,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/core/src/main/java/feign/ResponseHandler.java#L65-L99","documentation":"In ResponseHandler.handleResponse, an IOException raised while reading/decoding the response is logged (if logLevel != NONE) and rethrown as a FeignException built by errorReading with message \"%s reading %s %s\". Any other exception triggers ensureClosed(response.body()) and propagates. It indicates the response arrived but its body could not be read or processed.","triggerScenarios":"Connection closed mid-body read (truncated response); body stream IO failure while the decoder consumes it; decompression failure on gzip-encoded bodies; reading a body after the connection was already released.","commonSituations":"Load balancer or proxy terminating the connection early; very large responses hitting socket timeouts mid-read; misconfigured gzip; calling response.body() again after a prior read.","solutions":["Check the wrapped IOException cause: premature EOF points to connection/proxy issues, timeout points to slow body transfer.","Increase read timeout in Request.Options for large payloads.","Verify proxy/LB idle timeouts are larger than the expected body transfer time.","Ensure the response body is read exactly once and Content-Encoding headers match the actual payload."],"exampleFix":"// before\nnew Request.Options(2000, 2000);\n// after\nnew Request.Options(5, TimeUnit.SECONDS, 60, TimeUnit.SECONDS, true);","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return api.download();\n} catch (FeignException e) {\n  if (e.getCause() instanceof IOException io && isTransient(io)) {\n    return retryWithBackoff(() -> api.download());\n  }\n  throw e;\n}","preventionTips":["Size read timeouts to the largest expected response body","Check LB/proxy idle timeouts exceed transfer duration","Only read the response body once per response","Verify Content-Encoding (gzip) is handled by the client configuration"],"tags":["io","response-body","network","decode"],"backgroundTag":"broken-pipe","analyzedSha":"e2a1e27560a1e68840c34f031afca88b36096e30","analyzedAt":"2026-09-10T12:37:37.238Z","contentChangedAt":"2026-09-10T12:37:37.238Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}