Pumpkin-MC/Pumpkin · error · AdvancementDataError
JSON error
Error message
JSON error: {0} What it means
PacketDecodeError::OutOfBounds is raised when the declared packet length is not within the valid bounds for decoding — typically a negative value, zero where data is required, or a length inconsistent with the remaining bytes in the buffer. The library validates the length before consuming the payload. It guards the decoder against impossible framing.
Solutions
- Check that the full packet body is buffered before decoding (read length, then wait for len bytes).
- Verify the connection was not closed/truncated mid-packet before interpreting the error.
- Treat the peer as misbehaving and close the connection; framing cannot be trusted after OutOfBounds.
- If parsing a captured/external byte stream, validate the length against buffer size before calling decode.
Example fix
// before
let body = reader.read_exact(len as usize).await?; // len may exceed available bytes
// after
if len < 0 || len as usize > reader.remaining() {
return Err(PacketDecodeError::OutOfBounds);
}
let body = reader.read_exact(len as usize).await?; Defensive patterns
Strategy: validation
Validate before calling
fn in_bounds(len: i32, available: usize) -> bool {
len > 0 && (len as usize) <= available
} Type guard
fn is_in_bounds(len: i64, available: usize) -> bool {
len > 0 && len <= available as i64
} Try / catch
match decode_packet(stream).await {
Err(PacketDecodeError::OutOfBounds) => { warn!("bad packet framing; closing connection"); break; }
Ok(p) => handle(p),
Err(e) => warn!("decode error: {e}"),
} Prevention
- Buffer the full declared packet before decoding its body.
- Check for EOF/truncation before interpreting framing errors.
- Never cast a length to usize without checking it is positive and fits available data.
- Treat framing violations as unrecoverable and close the connection.
When it happens
Trigger: Decoding a packet whose length VarInt decodes to a negative or otherwise invalid value; the declared length exceeds the bytes actually available in the read buffer.
Common situations: A truncated read (connection cut mid-packet) leaving fewer bytes than the declared length; corrupted or attacker-supplied length fields; a buggy client implementation producing malformed framing.
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
- IO error
- Authentication servers are down
- failed to decode packet ID
- Failed to verify username
- You are banned from Authentication servers
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/ec6a5b62e04d4dc7.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin/src/entity/player/advancement.rs:247
#[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(),
last_selected_tab: None,
}View on GitHub (pinned to 8d4639e25a)