{"record":{"id":"c8c24d9f01d3468f","repo":"apple/pkl","slug":"io-exception-during-decoding","errorCode":null,"errorMessage":"IO exception during decoding","messagePattern":"IO exception during decoding","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/util/pklbinary/AbstractPklBinaryDecoder.java","lineNumber":410,"sourceCode":"\n    DecodeIterator(int size) {\n      this.size = size;\n    }\n\n    public int getSize() {\n      return size;\n    }\n\n    public boolean hasNext() {\n      return idx < size;\n    }\n\n    public T next() {\n      currPath.push(idx);\n      try {\n        return getNext();\n      } catch (IOException e) {\n        throw doIOFail(e);\n      } finally {\n        currPath.pop();\n        idx++;\n      }\n    }\n\n    abstract T getNext() throws IOException;\n  }\n\n  protected class ObjectDecodeIterator extends DecodeIterator<DecodedObjectMember> {\n    ObjectDecodeIterator(int size) {\n      super(size);\n      checkCollectionLength(size, \"object\");\n    }\n\n    @Override\n    DecodedObjectMember getNext() throws IOException {\n      var memberLen = unpacker.unpackArrayHeader();","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/util/pklbinary/AbstractPklBinaryDecoder.java#L392-L428","documentation":"The public next() of the decoder's element iterator wraps any IOException from getNext() via doIOFail, producing a failure whose message is \"IO exception during decoding\" (with the underlying cause attached). It surfaces I/O problems (e.g. reading from an underlying stream/channel) that occur while decoding the element at the current path.","triggerScenarios":"Iterating members/elements of a decoded container (member -> next) when the underlying input source (file channel, InputStream) throws IOException mid-decode: disk read failure, closed stream, socket reset while streaming the binary data.","commonSituations":"Decoding directly from a network stream that drops mid-read; reading from a file on a failing/unmounted disk; a stream closed by another thread or by try-with-resources before iteration finishes.","solutions":["Inspect the cause attached by doIOFail to find the real I/O problem (closed stream, permission, disk error) and fix that.","Ensure the InputStream/channel remains open for the whole decoding session; don't close it before iteration completes.","If reading over an unreliable transport, read the full payload into memory (or a local file) first, then decode from the stable buffer.","Add retry with backoff around the I/O acquisition step if the source is a remote, transiently-failing resource."],"exampleFix":"// before: stream closed too early\ntry (InputStream in = open()) {\n  iterator = decoder.decode(in).elements();\n}\nfor (T v : iterator) { ... } // IOException during decoding\n// after: keep stream open during iteration\ntry (InputStream in = open()) {\n  for (T v : decoder.decode(in).elements()) { ... }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try (InputStream in = openSource()) {\n  for (Iterator<T> it = decoder.decode(in).elements(); ; ) {\n    try {\n      T value = it.next();\n      consume(value);\n    } catch (IOException e) {\n      throw new SourceReadException(\"IO exception during decoding\", e); // inspect cause\n    }\n  }\n}","preventionTips":["Keep the underlying stream open for the entire iteration; close it only after decoding finishes.","Prefer reading the full payload into memory or a temp file before decoding when the source is a network stream.","Add retry logic around the acquisition of remote inputs for transient I/O failures."],"tags":["io","binary-decoding","stream"],"backgroundTag":"file-read-failed","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}