Pumpkin-MC/Pumpkin · error

item string array length out of bounds

Error message

item string array length out of bounds

What it means

This error is thrown while decoding an ItemComponentPacket's user data from a Bedrock client. The packet contains two string arrays (place_on_blocks and destroy_blocks), each prefixed with an i32 count. The library rejects any declared count below 0 or above 1024 because a hostile or malformed count would otherwise cause enormous allocations or long decode loops.

Solutions

  1. Verify the client and server protocol versions match; a desync shifts field boundaries and corrupts the length field.
  2. Check the sending mod/client code that builds the item user data to ensure it writes correct array counts.
  3. Capture and inspect the raw packet payload to confirm whether the bytes are misaligned or genuinely out of range.
  4. If the value is genuinely large, reduce the number of place_on_blocks/destroy_blocks entries sent (limit is 1024).

Example fix

// before: sending arbitrary-length arrays
let place_on: Vec<String> = load_all_blocks(); // may exceed 1024
// after
let place_on: Vec<String> = load_all_blocks().into_iter().take(1024).collect();
Defensive patterns

Strategy: validation

Validate before calling

fn validate_string_array_len(len: i32) -> Result<(), String> {
    if !(0..=1024).contains(&len) {
        return Err(format!("array length {len} out of range 0..=1024"));
    }
    Ok(())
}

Try / catch

match packet_result {
    Err(e) if e.to_string().contains("out of bounds") => {
        log::warn!("dropping malformed item packet: {e}");
        // disconnect or ignore peer
    }
    other => other?,
}

Prevention

When it happens

Trigger: Triggered by ItemComponentPacket::read -> read_user_data when the i32 array length field for place_on_blocks or destroy_blocks parses to a negative value or a value greater than 1024.

Common situations: Malicious or corrupted packets from untrusted clients, protocol version mismatches where the client serializes the array differently, desynchronized stream parsing that reads garbage bytes as the length field.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09). Data as JSON: /api/errors/94894ed81e2f9e17. Report an issue: GitHub.

Appendix: source

Thrown at crates/pumpkin-protocol/src/bedrock/network_item.rs:569

    }
}

fn write_user_data_strings<W: Write>(writer: &mut W, values: &[String]) -> Result<(), Error> {
    (values.len() as i32).write(writer)?;
    for value in values {
        let bytes = value.as_bytes();
        let len = u16::try_from(bytes.len())
            .map_err(|_| Error::new(std::io::ErrorKind::InvalidInput, "item string too long"))?;
        writer.write_all(&len.to_be_bytes())?;
        writer.write_all(bytes)?;
    }
    Ok(())
}

fn read_user_data_strings<R: Read>(reader: &mut R) -> Result<Vec<String>, Error> {
    let len = i32::read(reader)?;
    if !(0..=1024).contains(&len) {
        return Err(Error::new(
            std::io::ErrorKind::InvalidData,
            "item string array length out of bounds",
        ));
    }
    let mut values = Vec::with_capacity((len as usize).min(32));
    for _ in 0..len {
        let mut length = [0; 2];
        reader.read_exact(&mut length)?;
        let str_len = usize::from(u16::from_be_bytes(length));
        if str_len > 32767 {
            return Err(Error::new(
                std::io::ErrorKind::InvalidData,
                "item string too long",
            ));
        }
        let mut bytes = vec![0; str_len];
        reader.read_exact(&mut bytes)?;
        values.push(

View on GitHub (pinned to 8d4639e25a)