{"record":{"id":"3d249a6f3512af6f","repo":"Pumpkin-MC/Pumpkin","slug":"string-from-utf8-error","errorCode":null,"errorMessage":"String::from_utf8 error","messagePattern":"String::from_utf8 error","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pumpkin-protocol/src/bedrock/network_item.rs","lineNumber":589,"sourceCode":"            \"item string array length out of bounds\",\n        ));\n    }\n    let mut values = Vec::with_capacity((len as usize).min(32));\n    for _ in 0..len {\n        let mut length = [0; 2];\n        reader.read_exact(&mut length)?;\n        let str_len = usize::from(u16::from_be_bytes(length));\n        if str_len > 32767 {\n            return Err(Error::new(\n                std::io::ErrorKind::InvalidData,\n                \"item string too long\",\n            ));\n        }\n        let mut bytes = vec![0; str_len];\n        reader.read_exact(&mut bytes)?;\n        values.push(\n            String::from_utf8(bytes)\n                .map_err(|error| Error::new(std::io::ErrorKind::InvalidData, error))?,\n        );\n    }\n    Ok(values)\n}\n\nfn read_user_data(\n    user_data: Vec<u8>,\n    is_shield: bool,\n) -> Result<(Nbt, Vec<String>, Vec<String>, i64), Error> {\n    if user_data.is_empty() {\n        return Ok((Nbt::default(), Vec::new(), Vec::new(), 0));\n    }\n\n    let mut cursor = std::io::Cursor::new(user_data);\n    let nbt_version = i16::read(&mut cursor)?;\n    let nbt_data = if nbt_version == -1 {\n        let _version = i8::read(&mut cursor)?;\n        let mut nbt_reader = NbtReadHelperBedrock::new(&mut cursor);","sourceCodeStart":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-protocol/src/bedrock/network_item.rs#L571-L607","documentation":"This error wraps a String::from_utf8 failure when converting decoded bytes of a user-data string into a Rust String. It means the byte sequence in the packet is not valid UTF-8, so the library rejects the packet rather than producing lossy text.","triggerScenarios":"Triggered in read_user_data_strings after read_exact loads str_len bytes and String::from_utf8 fails because the bytes are not valid UTF-8.","commonSituations":"Clients sending non-UTF-8 encoded text (e.g. legacy encodings), corrupted packets, stream misalignment slicing a multi-byte UTF-8 character.","solutions":["Validate that the client encodes strings as UTF-8 before sending.","Check for stream misalignment: an earlier field read with the wrong size shifts subsequent string boundaries.","Inspect the failing bytes; if they are legacy-encoded, convert the sender to UTF-8.","On the server side, consider rejecting the offending client packet cleanly and logging the peer."],"exampleFix":"// sender before: raw bytes, non-UTF-8\nwriter.write_all(&latin1_bytes)?;\n// after\nwriter.write_all(String::from_utf8(latin1_bytes_lossy)?.as_bytes())?;","handlingStrategy":"try-catch","validationCode":"fn is_valid_utf8(bytes: &[u8]) -> bool {\n    std::str::from_utf8(bytes).is_ok()\n}","typeGuard":"fn as_utf8(bytes: &[u8]) -> Option<&str> {\n    std::str::from_utf8(bytes).ok()\n}","tryCatchPattern":"match read_user_data_strings(&mut cursor) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {\n        log::warn!(\"non-UTF-8 string in item user data: {e}; dropping packet\");\n    }\n    other => other?,\n}","preventionTips":["Always encode strings as UTF-8 on the client","Validate field alignment: a misread prior field splits multi-byte characters","Test with non-ASCII block names to catch encoding bugs early"],"tags":["bedrock","protocol","utf-8","deserialization"],"backgroundTag":"invalid-argument-format","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}