{"record":{"id":"879d61497734ebc6","repo":"apache/hadoop","slug":"s-closed-879d61","errorCode":null,"errorMessage":"%s closed","messagePattern":"(.+?) closed","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/erasurecode/rawcoder/AbstractNativeRawEncoder.java","lineNumber":53,"sourceCode":"  public static Logger LOG =\n      LoggerFactory.getLogger(AbstractNativeRawEncoder.class);\n\n  // Protect ISA-L coder data structure in native layer from being accessed and\n  // updated concurrently by the init, release and encode functions.\n  protected final ReentrantReadWriteLock encoderLock =\n      new ReentrantReadWriteLock();\n\n  public AbstractNativeRawEncoder(ErasureCoderOptions coderOptions) {\n    super(coderOptions);\n  }\n\n  @Override\n  protected void doEncode(ByteBufferEncodingState encodingState)\n      throws IOException {\n    encoderLock.readLock().lock();\n    try {\n      if (nativeCoder == 0) {\n        throw new IOException(String.format(\"%s closed\",\n            getClass().getSimpleName()));\n      }\n      int[] inputOffsets = new int[encodingState.inputs.length];\n      int[] outputOffsets = new int[encodingState.outputs.length];\n      int dataLen = encodingState.inputs[0].remaining();\n\n      ByteBuffer buffer;\n      for (int i = 0; i < encodingState.inputs.length; ++i) {\n        buffer = encodingState.inputs[i];\n        inputOffsets[i] = buffer.position();\n      }\n\n      for (int i = 0; i < encodingState.outputs.length; ++i) {\n        buffer = encodingState.outputs[i];\n        outputOffsets[i] = buffer.position();\n      }\n\n      performEncodeImpl(encodingState.inputs, inputOffsets, dataLen,","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/erasurecode/rawcoder/AbstractNativeRawEncoder.java#L35-L71","documentation":"Native raw encoders (ISA-L backed, e.g. NativeRSRawEncoder) keep a long nativeCoder handle that becomes 0 once close() releases the native coder. A later doEncode sees nativeCoder == 0 and throws IOException(\"<ClassName> closed\"): the encoder instance is a closed native resource and must not be reused.","triggerScenarios":"Calling encode() on a native RawErasureEncoder that was already closed — via explicit close(), try-with-resources on a shared/pooled instance, or a cleanup hook racing with subsequent encodes.","commonSituations":"Encoder pools whose error handling closes instances still in circulation; wrapping long-lived encoders in try-with-resources; retry logic that reuses an encoder after an earlier failure path closed it.","solutions":["Create a new encoder (CodecUtil.createRawEncoder / RawErasureCoderFactory) instead of reusing a closed one","Match encoder lifetime to workload scope; never let pools return closed instances","On any exception path that closes an encoder, evict it from caches immediately"],"exampleFix":"// before\ntry (RawErasureEncoder enc = CodecUtil.createRawEncoder(conf, \"rs\", opts)) {\n  enc.encode(inputs, outputs);\n}\nenc.encode(moreInputs, moreOutputs); // reused after close -> IOException\n\n// after\nRawErasureEncoder enc = CodecUtil.createRawEncoder(conf, \"rs\", opts);\nenc.encode(inputs, outputs);\nenc.encode(moreInputs, moreOutputs);\nenc.close(); // close only when truly done","handlingStrategy":"try-catch","validationCode":"// Keep encoder lifetime explicit: one encoder per workload batch\nRawErasureEncoder encoder = CodecUtil.createRawEncoder(conf, \"rs\", opts);\ntry {\n  encoder.encode(inputs, outputs);\n} finally {\n  encoder.close(); // close only when no more encodes are needed\n}","typeGuard":null,"tryCatchPattern":"try {\n  encoder.encode(inputs, outputs);\n} catch (IOException e) {\n  if (e.getMessage().endsWith(\"closed\")) {\n    encoder = CodecUtil.createRawEncoder(conf, \"rs\", opts);\n    encoder.encode(inputs, outputs); // one retry with a fresh encoder\n  } else throw e;\n}","preventionTips":["Do not wrap pooled/long-lived native encoders in try-with-resources","On exception paths that close an encoder, always remove it from caches","Log close() calls on shared coders during development to catch lifecycle bugs"],"tags":["erasure-coding","native","isal","resource-lifecycle","ioexception"],"backgroundTag":"use-after-close","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}