Pumpkin-MC/Pumpkin · warning · InventoryError

Out of order dragging

Error message

Out of order dragging

What it means

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.

Solutions

  1. Reset the container's drag state and discard the out-of-order packet
  2. Require clients to restart the drag sequence from Start
  3. Add a drag-state timeout so stale sequences never persist across ticks
  4. Log the offending player and packet type to detect modified clients

Example fix

// before
container.handle_drag_packet(player_id, packet)?; // may be End before Start
// after
if !container.drag_in_progress(player_id) && packet.is_drag_end() {
    log::debug!("discarding out-of-order drag end from {player_id}");
    return Ok(());
}
container.handle_drag_packet(player_id, packet)?;
Defensive patterns

Strategy: validation

Validate before calling

fn drag_packet_is_expected(state: DragState, packet: &DragPacket) -> bool {
    match state {
        DragState::Idle => matches!(packet, DragPacket::Start(_)),
        DragState::InProgress => matches!(packet, DragPacket::Add(_) | DragPacket::End),
    }
}

Try / catch

match container.handle_drag_packet(player_id, packet) {
    Err(InventoryError::OutOfOrderDragging) => {
        log::debug!("out-of-order drag from {player_id}; resetting drag state");
        container.reset_drag(player_id);
    }
    r => r?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09). Data as JSON: /api/errors/649d7598f6832263. Report an issue: GitHub.

Appendix: source

Thrown at crates/pumpkin-inventory/src/error.rs:24

/// interactions, such as invalid slot indices, permission issues, or protocol errors.
#[derive(Error, Debug)]
pub enum InventoryError {
    /// Failed to acquire a lock on an inventory or slot.
    #[error("Unable to lock")]
    LockError,
    /// The specified slot index is invalid or out of bounds.
    #[error("Invalid slot")]
    InvalidSlot,
    /// A player attempted to interact with a container that is closed.
    ///
    /// The parameter is the player's entity ID.
    #[error("Player '{0}' tried to interact with a closed container")]
    ClosedContainerInteract(i32),
    /// Multiple players attempted to drag items in the same container simultaneously.
    #[error("Multiple players dragging in a container at once")]
    MultiplePlayersDragging,
    /// Drag operation was performed out of order (e.g., end before start).
    #[error("Out of order dragging")]
    OutOfOrderDragging,
    /// The received inventory packet is malformed or invalid.
    #[error("Invalid inventory packet")]
    InvalidPacket,
    /// The player lacks permission to perform this inventory operation.
    #[error("Player does not have enough permissions")]
    PermissionError,
}

View on GitHub (pinned to 8d4639e25a)