apple/pkl · error · DecodeException

Unexpected EOF

Error message

Unexpected EOF

What it means

DecodeException wrapping a MessageInsufficientBufferException raised while reading the msgpack stream. It means the Pkl binary (msgpack-encoded) payload ended before the decoder finished reading a complete value. The library throws it from decode() whenever the underlying unpacker runs out of bytes mid-message.

Solutions

  1. Regenerate or re-fetch the binary Pkl data; the payload is truncated, so it must be re-produced in full
  2. Check that the InputStream/byte[] passed to the decoder is complete (verify byte counts / file sizes against the producer's output)
  3. Ensure the producer and consumer use compatible Pkl versions so msgpack framing matches
  4. If reading from a network/file stream, verify the read loop reads until EOF rather than a fixed byte count

Example fix

// before
byte[] buf = new byte[512];
int n = in.read(buf);
Object v = decoder.decode(Arrays.copyOf(buf, n)); // truncated
// after
Object v;
try (InputStream in = Files.newInputStream(path)) {
  v = decoder.decode(in.readAllBytes()); // read to EOF
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: verify the payload is complete before decoding
if (bytes == null || bytes.length == 0) {
  throw new IOException("empty pkl binary payload");
}
// when reading streams, read fully:
byte[] all = in.readAllBytes();

Type guard

static boolean looksComplete(byte[] b) { return b != null && b.length > 0; }

Try / catch

try {
  Object v = decoder.decode(bytes);
} catch (DecodeException e) {
  if ("Unexpected EOF".equals(e.getMessage())) {
    // regenerate/re-fetch payload or surface a 'corrupt binary data' error
  } else throw e;
}

Prevention

When it happens

Trigger: Calling decode()/first()/second() (or a subclass such as the evaluator's binary module decoder) with a truncated InputStream or byte[]; a producer (e.g. pkl server or cached module bytes) wrote fewer bytes than the msgpack header declares; the file/network stream was cut off mid-object.

Common situations: Corrupted or partially downloaded .pkl binary caches; version mismatch where a writer produced a newer format that the reader's unpacker mis-parses; passing an empty stream to decode(); truncation when copying evaluator output between processes.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/c481c1c92918b161. Report an issue: GitHub.

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/util/pklbinary/AbstractPklBinaryDecoder.java:70

  protected AbstractPklBinaryDecoder(MessageUnpacker unpacker, int collectionSizeLimit) {
    this.unpacker = unpacker;
    this.collectionSizeLimit = collectionSizeLimit;
  }

  protected static class DecodeException extends RuntimeException {
    public DecodeException(String msg, Object... args) {
      super(new Formatter().format(msg, args).toString());
    }
  }

  protected final Object decode() {
    currPath = new ArrayDeque<>();
    try {
      try {
        return doDecode();
      } catch (MessageInsufficientBufferException e) {
        throw new DecodeException("Unexpected EOF", e);
      }
    } catch (IOException e) {
      throw doIOFail(e);
    } catch (MessagePackException | DecodeException e) {
      var path = new ArrayList<String>(currPath.size());
      for (var iter = currPath.descendingIterator(); iter.hasNext(); ) {
        path.add(iter.next().toString());
      }
      Collections.reverse(path);
      throw doFail(e, unpacker.getTotalReadBytes(), path);
    }
  }

  private void assertLength(PklBinaryCode type, int len, int expected) {
    if (len < expected) {
      throw new DecodeException(
          "Expected %s structure to have at least %d slots, found %d", type, expected + 1, len);
    }

View on GitHub (pinned to f3efcbfc9b)