{"record":{"id":"1d08abb7836e9aff","repo":"apache/hadoop","slug":"exception-occurred-while-closing-channel-s","errorCode":null,"errorMessage":"Exception occurred while closing channel '%s'","messagePattern":"Exception occurred while closing channel '(.+?)'","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorageClientReadChannel.java","lineNumber":171,"sourceCode":"\n  @Override\n  public SeekableByteChannel truncate(long size) throws IOException {\n    throw new UnsupportedOperationException(\"Cannot mutate read-only channel\");\n  }\n\n  @Override\n  public boolean isOpen() {\n    return open;\n  }\n\n  @Override\n  public void close() throws IOException {\n    if (open) {\n      try {\n        LOG.trace(\"Closing channel for '{}'\", resourceId);\n        contentReadChannel.closeContentChannel();\n      } catch (Exception e) {\n        throw new IOException(\n            String.format(\"Exception occurred while closing channel '%s'\", resourceId), e);\n      } finally {\n        contentReadChannel = null;\n        open = false;\n      }\n    }\n  }\n\n  /**\n   * This class own the responsibility of opening up contentChannel. It also implements the Fadvise,\n   * which helps in deciding the boundaries of content channel being opened and also caching the\n   * footer of an object.\n   */\n  private class ContentReadChannel {\n\n    // Size of buffer to allocate for skipping bytes in-place when performing in-place seeks.\n    private static final int SKIP_BUFFER_SIZE = 8192;\n    private final BlobId blobId;","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorageClientReadChannel.java#L153-L189","documentation":"GoogleCloudStorageClientReadChannel.close() wraps any exception thrown by contentReadChannel.closeContentChannel() into IOException \"Exception occurred while closing channel '<resourceId>'\". The finally block still nulls the channel and clears the open flag, so the channel ends up closed even when the underlying HTTP stream close failed; the original failure is preserved as the cause. Whether this matters depends on whether the read side already succeeded.","triggerScenarios":"Closing a read channel whose underlying storage ReadChannel/HTTP connection errors during close: connection reset by peer or proxy, connection already killed by an idle timeout (e.g. LB ~10 min), or closing after a prior read error left the stream broken.","commonSituations":"Flaky networks where the final FIN/RST fails; Spark/Hadoop task cleanup closing thousands of channels during network degradation; connections reaped by middleboxes; double-close after a failed read.","solutions":["Inspect the cause: if all reads already completed successfully, log and continue — the exception is usually benign at that point.","Structure code so a close-time failure never masks the primary result: track whether the body was fully read, and only propagate close errors when it wasn't.","If close errors correlate with read errors or one specific host, fix the underlying network/proxy/idle-timeout problem.","Upgrade the connector and google-cloud-storage client, which have received close-robustness fixes."],"exampleFix":"// before\nch.close(); // close failure masks the successful read result\n\n// after\nboolean readComplete = /* all bytes consumed */;\ntry {\n  ch.close();\n} catch (IOException closeErr) {\n  if (!readComplete) throw closeErr;\n  LOG.warn(\"Ignoring close failure after complete read: {}\", closeErr.toString());\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"boolean readComplete = bytesConsumed == expectedBytes;\ntry {\n  ch.close();\n} catch (IOException closeErr) {\n  if (!readComplete) throw closeErr;      // data may be missing: propagate\n  LOG.warn(\"close failed after complete read: {}\", closeErr.toString()); // benign\n}","preventionTips":["Track whether the body was fully read so close failures can be classified benign vs data-loss.","Never let a close exception replace an earlier, more meaningful read exception — close guarded inside catch/finally.","Keep client-side keep-alive/proxy idle timeouts above expected read gaps to avoid half-dead connections at close."],"tags":["gcs","close","resource-cleanup","network","read-channel"],"backgroundTag":"channel-close-failure","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}