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
- Truncate or reject strings longer than 65535 bytes before building the packet.
- Validate at the plugin API boundary where players can submit text (names, lore).
- Measure byte length (value.len()), not character count — multi-byte characters count more.
- 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
- Validate player-supplied item names/lore at the plugin API boundary.
- Check byte length (str::len), not character count — UTF-8 multi-byte chars count more.
- Truncate on a char boundary to avoid corrupting text.
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
- durability correction must fit in an i16
- item stack response count exceeds 4096
- user_data_len exceeds 1MB limit
- extra_data_len exceeds 1MB limit
- Invalid ContainerName ID
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)