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
- Regenerate or re-fetch the binary Pkl data; the payload is truncated, so it must be re-produced in full
- Check that the InputStream/byte[] passed to the decoder is complete (verify byte counts / file sizes against the producer's output)
- Ensure the producer and consumer use compatible Pkl versions so msgpack framing matches
- 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
- Always read streams to EOF before decoding; never decode fixed-size prefixes
- Validate producer output byte counts against expectations (checksums, size headers)
- Keep producer and consumer Pkl versions aligned
- Treat binary caches as disposable: on EOF, invalidate and re-generate
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
- Expected structure to have at least slots, found
- Unexpected empty object array value
- Unexpected msgpack bin value
- Unexpected msgpack ext value
- Unexpected msgpack map value
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)