Pumpkin-MC/Pumpkin · error · AdvancementDataError

IO error

Error message

IO error: {0}

What it means

PacketDecodeError::TooLong is raised when the length prefix read from an incoming Minecraft protocol packet exceeds the maximum allowed packet size. The library enforces this limit to prevent malicious or corrupted clients from causing huge allocations or memory exhaustion. It is thrown during packet decoding before any payload is read.

Solutions

  1. Verify the length prefix on the wire matches the actual packet size (check for stream desynchronization).
  2. Ensure compression settings (threshold, enabled/disabled) match between client and server.
  3. Log the offending length value and drop/ban clients that repeatedly send oversized packets.
  4. If the limit is legitimately too small for your packets, raise the maximum length in the protocol configuration.

Example fix

// before
let len = reader.read_var_int().await?; // no upper-bound check, decodes into TooLong later
// after
let len = reader.read_var_int().await?;
if len > MAX_PACKET_SIZE {
    return Err(PacketDecodeError::TooLong);
}
Defensive patterns

Strategy: validation

Validate before calling

fn validate_packet_len(len: i32, max: i32) -> Result<(), PacketDecodeError> {
    if len <= 0 || len > max { return Err(PacketDecodeError::TooLong); }
    Ok(())
}

Type guard

fn is_valid_packet_len(len: i32, max: i32) -> bool {
    len > 0 && len <= max
}

Try / catch

match decode_packet(stream).await {
    Err(PacketDecodeError::TooLong) => { warn!("oversized packet from peer; dropping connection"); drop(stream); }
    Err(e) => warn!("decode error: {e}"),
    Ok(p) => handle(p),
}

Prevention

When it happens

Trigger: Calling the packet decode/read path on a connection whose length VarInt decodes to a value above the configured maximum packet length; feeding a byte stream with a corrupted or hostile length prefix.

Common situations: Malicious clients or bots sending oversized length fields; a desynchronized stream where a payload byte is misread as a length VarInt; mismatched compression settings between client and server shifting the framing.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at crates/pumpkin/src/entity/player/advancement.rs:245

impl AdvancementAward {
    #[must_use]
    pub(crate) const fn awarded(self) -> bool {
        self.awarded
    }

    pub(crate) const fn combine(self, other: Self) -> Self {
        Self {
            awarded: self.awarded || other.awarded,
            completed: self.completed || other.completed,
        }
    }
}

/// Errors that can occur when saving or loading advancement data.
#[derive(Debug, thiserror::Error)]
pub enum AdvancementDataError {
    #[error("IO error: {0}")]
    Io(std::io::Error),
    #[error("JSON error: {0}")]
    Json(serde_json::Error),
}

impl PlayerAdvancement {
    /// Creates a new instance of `PlayerAdvancement`.
    #[must_use]
    pub fn new(manager: Arc<AdvancementManager>, uuid: Uuid) -> Self {
        Self {
            progress: AdvancementProgressMap::default(),
            path: manager.advancement_path.join(format!("{uuid}.json")),
            manager,
            player: Weak::new(),
            is_first_packet: true,
            roots_to_update: HashSet::default(),
            visible: HashSet::default(),
            progress_changed: HashSet::default(),

View on GitHub (pinned to 8d4639e25a)