Pumpkin-MC/Pumpkin · error

missing inventory action data

Error message

missing inventory action data

What it means

Thrown while decoding InventoryTransactionPacket when the presence bool before the inventory actions list is false. The library requires the actions collection to be present in every transaction packet.

Solutions

  1. Verify the transaction type VarUInt was read with correct varint encoding (a truncated varint shifts everything after).
  2. Ensure the client writes a true presence bool before the actions length.
  3. Check protocol version agreement for InventoryTransactionPacket field order.
  4. Hand-decode the raw bytes from the packet start to find where the stream diverged.

Example fix

// sender before: omitting actions presence flag
write_varuint(buf, actions.len())?;
// after
buf.push(0x01); // presence bool: true
write_varuint(buf, actions.len())?;
Defensive patterns

Strategy: try-catch

Try / catch

match InventoryTransactionPacket::read(buf) {
    Err(e) if e.to_string().contains("missing inventory action data") => {
        log::warn!("transaction packet missing required actions flag: {e}; dropping");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Triggered by InventoryTransactionPacket::read when bool::read(buf) returns false immediately after reading the transaction_type VarUInt.

Common situations: Stream desynchronization after a misread field, client implementations omitting the actions presence flag, protocol version differences in the packet layout.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at crates/pumpkin-protocol/src/bedrock/server/inventory_transaction.rs:195

        let mut legacy_set_item_slots = Vec::new();
        if has_legacy_slots {
            let len = collection_length(buf, "legacy item slot groups")?;
            legacy_set_item_slots.reserve(len);
            for _ in 0..len {
                legacy_set_item_slots.push(LegacySetItemSlot::read(buf)?);
            }
        }

        if !bool::read(buf)? {
            return Err(Error::new(
                ErrorKind::InvalidData,
                "missing inventory transaction type",
            ));
        }
        let transaction_type = VarUInt::read(buf)?;

        if !bool::read(buf)? {
            return Err(Error::new(
                ErrorKind::InvalidData,
                "missing inventory action data",
            ));
        }
        let actions_len = collection_length(buf, "inventory actions")?;
        let mut actions = Vec::with_capacity(actions_len);
        for _ in 0..actions_len {
            actions.push(InventoryAction::read(buf)?);
        }
        let has_value = !actions.is_empty();

        let transaction_data = match transaction_type.0 {
            0 => TransactionData::Normal(NormalTransactionData::read(buf)?),
            1 => TransactionData::Mismatch(MismatchTransactionData::read(buf)?),
            2 => TransactionData::UseItem(UseItemTransactionData::read(buf)?),
            3 => TransactionData::UseItemOnEntity(UseItemOnEntityTransactionData::read(buf)?),
            4 => TransactionData::ReleaseItem(ReleaseItemTransactionData::read(buf)?),
            _ => {

View on GitHub (pinned to 8d4639e25a)