Pumpkin-MC/Pumpkin · error

item string too long

Error message

item string too long

What it means

Raised by write_user_data_strings when a user-data string's UTF-8 encoding exceeds u16::MAX bytes (65535). The Bedrock format prefixes each string with a u16 big-endian length, so longer strings cannot be encoded; the writer converts the try_from failure into an InvalidInput error.

Solutions

  1. Truncate or reject strings longer than 65535 bytes before building the packet.
  2. Validate at the plugin API boundary where players can submit text (names, lore).
  3. Measure byte length (value.len()), not character count — multi-byte characters count more.
  4. Split oversized text into multiple entries if the format allows.

Example fix

// before
values.push(user_supplied_name); // may exceed 65535 bytes
// after
const MAX: usize = u16::MAX as usize;
values.push(if user_supplied_name.len() > MAX {
    truncate_at_char_boundary(&user_supplied_name, MAX)
} else { user_supplied_name });
Defensive patterns

Strategy: validation

Validate before calling

fn string_fits_u16(s: &str) -> bool { s.len() <= u16::MAX as usize }
// check before pushing into user data strings
assert!(string_fits_u16(&name), "item string too long");

Type guard

fn truncate_utf16_safe(s: &str, max_bytes: usize) -> String {
    if s.len() <= max_bytes { return s.to_string(); }
    let mut end = max_bytes;
    while !s.is_char_boundary(end) { end -= 1; }
    s[..end].to_string()
}

Try / catch

packet.write(&mut writer).map_err(|e| {
    if e.to_string() == "item string too long" {
        log::error!("user-data string exceeded 65535 bytes");
    }
    e
})?;

Prevention

When it happens

Trigger: Serializing item user data (e.g., custom item name, lore strings) where any string's byte length > 65535 and calling the packet write path.

Common situations: Plugins setting absurdly long custom item names/lore from user input; concatenating text without a length check; multi-byte UTF-8 (emoji, CJK) pushing a string past the byte cap even when char count seems small.

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/049e66e10b905f1d. Report an issue: GitHub.

Appendix: source

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

        let mut extra_data = vec![0u8; extra_data_len];
        buf.read_exact(&mut extra_data)?;

        Ok(Self {
            id,
            count,
            aux_value,
            block_runtime_id,
            extra_data,
        })
    }
}

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)?;

View on GitHub (pinned to 8d4639e25a)