Pumpkin-MC/Pumpkin · error · Error

Negative list length

Error message

Negative list length: {0}

What it means

Error::NegativeLength(i32) is raised when a list or byte/int/long array tag declares a negative element count while decoding. NBT lengths are i32 but must be >= 0; a negative value cannot describe a real array. The library throws it to prevent absurd allocations and to signal corrupt or maliciously crafted data. The i32 payload is the declared (negative) length.

Solutions

  1. Treat the input as corrupt: reject the packet/file and log the declared length and offset for diagnosis.
  2. Check endianness — Bedrock NBT is little-endian; reading it big-endian corrupts length fields.
  3. Verify stream alignment from the start of the document; a single earlier misread cascades into the length field.
  4. If the source is untrusted, keep the crate's bounds in mind and never bypass them with your own length handling.

Example fix

// before: reading Bedrock data with the Java (big-endian) reader
let nbt = Nbt::from_reader(&mut bedrock_data)?;
// after
let nbt = Nbt::from_reader_bedrock(&mut bedrock_data)?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: reject untrusted NBT unless the source is verified
fn looks_trusted(source: &DataSource) -> bool { source.is_authenticated() }

Try / catch

match Nbt::from_reader(&mut reader) {
    Err(pumpkin_nbt::Error::NegativeLength(n)) => eprintln!("corrupt/crafted data: len {n}"),
    Err(e) => return Err(e.into()),
    Ok(nbt) => nbt,
}

Prevention

When it happens

Trigger: Decoding NBT whose list/array length field is negative (corrupt file or crafted packet); stream desynchronization so a payload byte is read as part of the length, flipping its sign; reading Java big-endian data with a little-endian reader (or vice versa).

Common situations: Malicious client/server packets designed to trigger allocation bugs; corrupted world files; endianness mix-ups between Java and Bedrock variants; offset errors after a prior misparsed tag.

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


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

Appendix: source

Thrown at crates/pumpkin-nbt/src/lib.rs:95

    #[error("Encountered an unknown NBT tag id: {0}.")]
    UnknownTagId(u8),
    /// A Java CESU-8 string could not be decoded.
    #[error("Failed to Cesu 8 Decode")]
    Cesu8DecodingError,
    /// A string could not be decoded as UTF-8.
    #[error("Failed to UTF-8 Decode")]
    Utf8DecodingError,
    /// Serde reported an invalid value or serializer state.
    #[error("Serde error: {0}")]
    SerdeError(String),
    /// The requested Rust type has no NBT representation.
    #[error("NBT doesn't support this type: {0}")]
    UnsupportedType(String),
    /// The underlying reader or writer returned an I/O error.
    #[error("NBT reading was cut short: {0}")]
    Incomplete(io::Error),
    /// A list or array declared a negative element count.
    #[error("Negative list length: {0}")]
    NegativeLength(i32),
    /// A string, list, or array exceeded the supported length.
    #[error("Length too large: {0}")]
    LargeLength(usize),
    /// A Bedrock variable-length integer exceeded its maximum encoded size.
    #[error("Failed to decode varint - value too large")]
    VarIntTooLarge,
    /// A Bedrock variable-length long exceeded its maximum encoded size.
    #[error("Failed to decode varlong - value too large")]
    VarLongTooLarge,
    /// NBT nesting depth exceeded the maximum allowed limit.
    #[error("NBT depth exceeded maximum allowed limit")]
    MaxDepthExceeded,
    /// A list tag specified an invalid element tag type.
    #[error("Invalid element tag type for list: {0}")]
    InvalidListTag(u8),
}

View on GitHub (pinned to 8d4639e25a)