{"record":{"id":"6c5db8a7a5eb79ea","repo":"apache/hadoop","slug":"channel-should-be-a-selectablechannel","errorCode":null,"errorMessage":"Channel should be a SelectableChannel","messagePattern":"Channel should be a SelectableChannel","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/SocketIOWithTimeout.java","lineNumber":96,"sourceCode":"  }\n  \n  /** \n   * Utility function to check if channel is ok.\n   * Mainly to throw IOException instead of runtime exception\n   * in case of mismatch. This mismatch can occur for many runtime\n   * reasons.\n   */\n  static void checkChannelValidity(Object channel) throws IOException {\n    if (channel == null) {\n      /* Most common reason is that original socket does not have a channel.\n       * So making this an IOException rather than a RuntimeException.\n       */\n      throw new IOException(\"Channel is null. Check \" +\n                            \"how the channel or socket is created.\");\n    }\n    \n    if (!(channel instanceof SelectableChannel)) {\n      throw new IOException(\"Channel should be a SelectableChannel\");\n    }    \n  }\n  \n  /**\n   * Performs actual IO operations. This is not expected to block.\n   *  \n   * @param buf\n   * @return number of bytes (or some equivalent). 0 implies underlying\n   *         channel is drained completely. We will wait if more IO is \n   *         required.\n   * @throws IOException\n   */\n  abstract int performIO(ByteBuffer buf) throws IOException;  \n  \n  /**\n   * Performs one IO and returns number of bytes read or written.\n   * It waits up to the specified timeout. If the channel is \n   * not read before the timeout, SocketTimeoutException is thrown.","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/SocketIOWithTimeout.java#L78-L114","documentation":"checkChannelValidity requires the channel to be a SelectableChannel because the whole timeout mechanism is built on Selector.select readiness events. Channel types that cannot be registered with a Selector (e.g. FileChannel) are rejected with IOException.","triggerScenarios":"Constructing a SocketIOWithTimeout subclass (SocketInputStream/SocketOutputStream) with a non-selectable channel such as FileChannel or a custom Channel implementation.","commonSituations":"Adapting Hadoop's socket-timeout wrapper to non-socket transports; test harnesses injecting arbitrary channels; mixing file IO code into socket wrapper paths.","solutions":["Pass only selectable channels: SocketChannel, ServerSocketChannel, DatagramChannel","For non-selectable channels, do direct blocking IO with your own timeout/deadline handling","Guard with (channel instanceof SelectableChannel) before constructing the wrapper"],"exampleFix":"// before\nnew SocketInputStream(fileChannel, timeout); // FileChannel is not selectable\n\n// after\nnew SocketInputStream(socketChannel, timeout);","handlingStrategy":"fallback","validationCode":"if (!(channel instanceof SelectableChannel)) {\n  // use direct blocking IO with manual deadline handling\n  return readBlocking(channel, deadline);\n}\nreturn new SocketInputStream((SelectableChannel) channel, timeout);","typeGuard":"static boolean isSelectable(java.nio.channels.Channel c) {\n  return c instanceof java.nio.channels.SelectableChannel;\n}","tryCatchPattern":null,"preventionTips":["Pass only SocketChannel/ServerSocketChannel/DatagramChannel to select-based wrappers","Keep file IO out of socket wrapper paths"],"tags":["hadoop-common","network","nio","sockets","java"],"backgroundTag":"non-selectable-channel","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}