{"record":{"id":"c5881803ed57d63c","repo":"Pumpkin-MC/Pumpkin","slug":"name-length-len-exceeds-max-collection-length","errorCode":null,"errorMessage":"{name} length {len} exceeds {MAX_COLLECTION_LENGTH}","messagePattern":"(.+?) length (.+?) exceeds (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pumpkin-protocol/src/bedrock/server/inventory_transaction.rs","lineNumber":18,"sourceCode":"use std::io::{Error, ErrorKind, Read};\n\nuse pumpkin_macros::packet;\nuse pumpkin_util::math::position::BlockPos;\n\nuse crate::bedrock::network_item::NetworkItemDescriptor;\nuse crate::{\n    codec::{var_int::VarInt, var_uint::VarUInt, var_ulong::VarULong},\n    serial::PacketRead,\n};\nuse pumpkin_util::math::vector3::Vector3;\n\nconst MAX_COLLECTION_LENGTH: u32 = 1024;\n\nfn collection_length<R: Read>(reader: &mut R, name: &str) -> Result<usize, Error> {\n    let len = VarUInt::read(reader)?.0;\n    if len > MAX_COLLECTION_LENGTH {\n        return Err(Error::new(\n            ErrorKind::InvalidData,\n            format!(\"{name} length {len} exceeds {MAX_COLLECTION_LENGTH}\"),\n        ));\n    }\n    Ok(len as usize)\n}\n\npub const WINDOW_ID_INVENTORY: i32 = 0;\npub const WINDOW_ID_OFF_HAND: i32 = 119;\npub const WINDOW_ID_ARMOUR: i32 = 120;\npub const WINDOW_ID_UI: i32 = 124;\n\n#[derive(Debug, PartialEq, Eq)]\npub enum InventoryActionSource {\n    Container,\n    World,\n    Creative,\n    Todo,","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-protocol/src/bedrock/server/inventory_transaction.rs#L1-L36","documentation":"A generic guard in inventory_transaction decoding: collection_length() reads a VarUInt length for a named collection (e.g. 'inventory actions', 'requests') and rejects values above MAX_COLLECTION_LENGTH (1024). The message interpolates the collection name, actual length, and limit.","triggerScenarios":"Triggered whenever any collection in InventoryTransactionPacket (actions, legacy set item slots, requests, etc.) declares a VarUInt length greater than 1024.","commonSituations":"Malicious or buggy clients sending huge counts, stream desync after a prior misparse, mods generating oversized transaction batches.","solutions":["Check for earlier field misalignment in the transaction packet; one bad read shifts all following lengths.","Reduce transaction batch sizes on the client to at most 1024 entries.","Verify client and server protocol versions for the inventory transaction layout.","Inspect the raw packet to see which named collection is oversized and why."],"exampleFix":"// client before: batch everything in one packet\nlet actions = gather_all_pending_actions();\n// after: split into chunks\nfor chunk in gather_all_pending_actions().chunks(1024) {\n    send_transaction(chunk);\n}","handlingStrategy":"validation","validationCode":"fn validate_collection_len(len: u32) -> Result<(), String> {\n    const MAX: u32 = 1024;\n    if len > MAX {\n        return Err(format!(\"collection length {len} exceeds {MAX}\"));\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match InventoryTransactionPacket::read(buf) {\n    Err(e) if e.to_string().contains(\"exceeds 1024\") => {\n        log::warn!(\"oversized collection in transaction packet: {e}; dropping\");\n    }\n    other => other?,\n}","preventionTips":["Chunk large transaction batches into packets of at most 1024 entries","Check for desync earlier in the packet: one bad length read shifts all later ones","Log the collection name from the message to locate the offending field"],"tags":["bedrock","protocol","inventory","packet-decoding"],"backgroundTag":"value-out-of-range","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"}