Pumpkin-MC/Pumpkin · error
actions_len exceeds limit
Error message
actions_len exceeds limit
What it means
Hard sanity cap in SPlayerAuthInput's item-use transaction decoding: after reading the two boolean flags and the actions_len VarUInt, values above 1024 are rejected with InvalidData before any allocation loop. The offending input is the actions_len count declared by the client — a malicious or desynchronized client claiming an absurd number of inventory actions; the guard prevents huge pre-reservations and long loops.
Solutions
- Drop the offending auth-input packet
- Retain the length cap before reserving the vector
- Log the oversized actions count at debug level
Defensive patterns
Strategy: validation
Validate before calling
let actions_len = VarUInt::read(buf)?.0 as usize;
if actions_len > 1024 { return Err(...); } Try / catch
if let Err(e) = decode(&buf) {
if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains("exceeds limit") { drop_packet(); }
} Prevention
- Enforce per-packet size limits at the transport layer too
- Batch client-side actions to stay well under the 1024 cap
- Unit-test decoders with counts just over the limit
- Monitor for clients tripping length limits repeatedly
When it happens
Trigger: PlayerAuthInput packet where both gating bools are true and the VarUInt actions_len is > 1024.
Common situations: Clients with huge queued transaction batches, buggy client mods, or deliberately crafted oversized packets.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- slots_len exceeds limit
- item string array length out of bounds
- miss_count exceeds limit
- hit_count exceeds limit
- length exceeds
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/1bdb04f6759d534d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin-protocol/src/bedrock/server/player_auth_input.rs:182
let slots_len = VarUInt::read(buf)?.0 as usize;
if slots_len > 1024 {
return Err(Error::new(
ErrorKind::InvalidData,
"slots_len exceeds limit",
));
}
legacy_slots.reserve(slots_len.min(64));
for _ in 0..slots_len {
legacy_slots.push(
crate::bedrock::server::inventory_transaction::LegacySetItemSlot::read(buf)?,
);
}
}
let mut actions = Vec::new();
if bool::read(buf)? && bool::read(buf)? {
let actions_len = VarUInt::read(buf)?.0 as usize;
if actions_len > 1024 {
return Err(Error::new(
ErrorKind::InvalidData,
"actions_len exceeds limit",
));
}
actions.reserve(actions_len.min(64));
for _ in 0..actions_len {
actions.push(
crate::bedrock::server::inventory_transaction::InventoryAction::read(buf)?,
);
}
}
let transaction = PlayerUseItemTransactionData::read(buf)?;
Ok(Self {
legacy_request_id,
legacy_slots,
actions,
transaction,
})View on GitHub (pinned to 8d4639e25a)