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

  1. Ensure the entire NBT payload is buffered before deserializing
  2. Verify the read offset is at the true start of the NBT document
  3. 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

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


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)