{"record":{"id":"649d7598f6832263","repo":"Pumpkin-MC/Pumpkin","slug":"out-of-order-dragging","errorCode":null,"errorMessage":"Out of order dragging","messagePattern":"Out of order dragging","errorType":"exception","errorClass":"InventoryError","httpStatus":null,"severity":"warning","filePath":"crates/pumpkin-inventory/src/error.rs","lineNumber":24,"sourceCode":"/// interactions, such as invalid slot indices, permission issues, or protocol errors.\n#[derive(Error, Debug)]\npub enum InventoryError {\n    /// Failed to acquire a lock on an inventory or slot.\n    #[error(\"Unable to lock\")]\n    LockError,\n    /// The specified slot index is invalid or out of bounds.\n    #[error(\"Invalid slot\")]\n    InvalidSlot,\n    /// A player attempted to interact with a container that is closed.\n    ///\n    /// The parameter is the player's entity ID.\n    #[error(\"Player '{0}' tried to interact with a closed container\")]\n    ClosedContainerInteract(i32),\n    /// Multiple players attempted to drag items in the same container simultaneously.\n    #[error(\"Multiple players dragging in a container at once\")]\n    MultiplePlayersDragging,\n    /// Drag operation was performed out of order (e.g., end before start).\n    #[error(\"Out of order dragging\")]\n    OutOfOrderDragging,\n    /// The received inventory packet is malformed or invalid.\n    #[error(\"Invalid inventory packet\")]\n    InvalidPacket,\n    /// The player lacks permission to perform this inventory operation.\n    #[error(\"Player does not have enough permissions\")]\n    PermissionError,\n}\n","sourceCodeStart":6,"sourceCodeEnd":33,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin-inventory/src/error.rs#L6-L33","documentation":"InventoryError::OutOfOrderDragging indicates a drag operation was performed out of sequence, such as receiving a drag End (or Add-slot) packet before the corresponding Start packet. The drag state machine in the library requires Start -> Add* -> End ordering, and violations are rejected to prevent corrupt item distributions.","triggerScenarios":"A client sends a Drag End packet without a prior Start, sends Add-slot packets outside an active drag, or sends two Starts without an intervening End; also after server-side drag state was reset by a timeout while the client continues its sequence.","commonSituations":"Desynced client/server state after lag spikes or container reopen; modified clients sending crafted drag packets; drag state cleared by another error (e.g. MultiplePlayersDragging) mid-sequence.","solutions":["Reset the container's drag state and discard the out-of-order packet","Require clients to restart the drag sequence from Start","Add a drag-state timeout so stale sequences never persist across ticks","Log the offending player and packet type to detect modified clients"],"exampleFix":"// before\ncontainer.handle_drag_packet(player_id, packet)?; // may be End before Start\n// after\nif !container.drag_in_progress(player_id) && packet.is_drag_end() {\n    log::debug!(\"discarding out-of-order drag end from {player_id}\");\n    return Ok(());\n}\ncontainer.handle_drag_packet(player_id, packet)?;","handlingStrategy":"validation","validationCode":"fn drag_packet_is_expected(state: DragState, packet: &DragPacket) -> bool {\n    match state {\n        DragState::Idle => matches!(packet, DragPacket::Start(_)),\n        DragState::InProgress => matches!(packet, DragPacket::Add(_) | DragPacket::End),\n    }\n}","typeGuard":null,"tryCatchPattern":"match container.handle_drag_packet(player_id, packet) {\n    Err(InventoryError::OutOfOrderDragging) => {\n        log::debug!(\"out-of-order drag from {player_id}; resetting drag state\");\n        container.reset_drag(player_id);\n    }\n    r => r?,\n}","preventionTips":["Enforce Start -> Add* -> End ordering in a per-player drag state machine","Reset drag state on container close/reopen and on timeouts","Discard (don't propagate) out-of-order packets from clients","Log repeat offenders to detect modified clients"],"tags":["inventory","drag","state-machine","protocol","rust"],"backgroundTag":"invalid-state-transition","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}