Pumpkin-MC/Pumpkin · error · Error::Incomplete
unexpected EOF
Error message
unexpected EOF
What it means
Raised in read_string when the declared string length extends past the end of the underlying byte buffer. The library wraps an io::ErrorKind::UnexpectedEof in Error::Incomplete, meaning the NBT document was cut short.
Solutions
- Ensure the entire NBT payload is buffered before deserializing
- Verify the read offset is at the true start of the NBT document
- Check the transport for truncation (packet size limits, read loops)
Example fix
// before
let nbt = Nbt::deserialize(&packet_bytes[offset..]).unwrap();
// after
let slice = &packet_bytes[offset..];
if slice.len() < expected_min_len { return Err(TruncatedPacket); }
let nbt = Nbt::deserialize(slice)?; Defensive patterns
Strategy: validation
Validate before calling
fn slice_fits(buf: &[u8], pos: usize, len: usize) -> bool { pos.checked_add(len).map_or(false, |end| end <= buf.len()) } Try / catch
match result { Err(Error::Incomplete(e)) if e.kind() == UnexpectedEof => handle_truncated(), Ok(v) => use(v), Err(e) => propagate(e) } Prevention
- Accumulate the full packet before deserializing NBT
- Verify offsets when NBT is embedded in larger streams
- Persist/read files atomically to avoid truncation
When it happens
Trigger: NBT::deserialize called on a buffer where a string's length prefix points beyond available bytes — typically a truncated payload or a wrong starting offset.
Common situations: Packets split across network reads and passed to the deserializer before fully buffered, truncated level.dat files, or decoding NBT from the wrong offset in a larger byte stream.
Related errors
- Serde error
- NBT reading was cut short
- Length too large
- Failed to decode varint - value too large
- Failed to decode varlong - value too large
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/eb4c354d9423b516.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin-nbt/src/deserializer.rs:89
self.read_exact(&mut buf).map_err(Error::Incomplete)?;
Ok(buf[0])
}
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<()> {
self.read_exact(buf).map_err(Error::Incomplete)
}
fn seek_relative(&mut self, offset: i64) -> Result<()> {
self.seek(SeekFrom::Current(offset))
.map_err(Error::Incomplete)?;
Ok(())
}
fn read_string(&mut self, len: usize) -> Result<Cow<'a, str>> {
let pos = self.position() as usize;
let data_len = self.get_ref().len();
if pos + len > data_len {
return Err(Error::Incomplete(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"unexpected EOF",
)));
}
self.set_position((pos + len) as u64);
let data = self.get_ref();
let slice = &data[pos..pos + len];
if let Ok(s) = std::str::from_utf8(slice) {
Ok(Cow::Borrowed(s))
} else {
let string = cesu8::from_java_cesu8(slice).map_err(|_| Error::Cesu8DecodingError)?;
Ok(string)
}
}
fn read_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>> {
let pos = self.position() as usize;
let data_len = self.get_ref().len();View on GitHub (pinned to 8d4639e25a)