Pumpkin-MC/Pumpkin · error · Error

The root tag of the NBT file is not a compound tag…

Error message

The root tag of the NBT file is not a compound tag. Received tag id: {0}

What it means

Error::NoRootCompound(u8) is raised when decoding an NBT document whose root tag is not a compound (tag id 0x0A). The NBT crate requires a named root compound for full Nbt documents, so it reports the tag id it actually received. This typically means the bytes are not a valid NBT file, are compressed differently than assumed, or the stream is offset.

Solutions

  1. Check the first byte(s) of your data: gzip magic 0x1F 0x8B means compressed; wrap the reader in GzDecoder/FlateDecoder as appropriate before parsing.
  2. Confirm you are using the matching reader variant (Java disk NBT vs network NBT vs Bedrock network NBT) for your data source.
  3. Verify you are at offset 0 of the NBT document, not inside a wrapper format that prefixes other data.
  4. If the payload is legitimately a non-compound root tag, parse it as NbtTag instead of Nbt.

Example fix

// before
let nbt = Nbt::from_reader(&mut file)?;
// after: detect gzip first
let mut reader = if is_gzip(&mut file)? { GzDecoder::new(file) } else { file };
let nbt = Nbt::from_reader(&mut reader)?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: check gzip magic before decoding
fn is_gzip(mut r: impl Read) -> std::io::Result<bool> {
    let mut b = [0u8; 2];
    r.read_exact(&mut b)?;
    Ok(b == [0x1F, 0x8B])
}

Type guard

fn root_is_compound(first_tag_id: u8) -> bool { first_tag_id == pumpkin_nbt::COMPOUND_ID }

Try / catch

match Nbt::from_reader(&mut reader) {
    Err(pumpkin_nbt::Error::NoRootCompound(id)) => eprintln!("root tag id {id} - wrong format/compression?"),
    Err(e) => return Err(e.into()),
    Ok(nbt) => nbt,
}

Prevention

When it happens

Trigger: Calling Nbt::read/from_reader on data whose first tag id byte is not 0x0A; reading gzip data that is not actually gzipped (wrong first bytes); decoding a network/Bedrock payload with the wrong NBT variant (Java vs network vs Bedrock); reading a raw NbtTag where an Nbt document was expected.

Common situations: Loading a .dat/.schematic file that is uncompressed or zlib instead of gzip; pointing a reader at a misaligned offset in a container format; a version change where Minecraft switched root representation; passing network little-endian NBT to the Java reader.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

/// Numeric identifier for a list tag.
pub const LIST_ID: u8 = 0x09;
/// Numeric identifier for a compound tag.
pub const COMPOUND_ID: u8 = 0x0A;
/// Numeric identifier for an integer-array tag.
pub const INT_ARRAY_ID: u8 = 0x0B;
/// Numeric identifier for a long-array tag.
pub const LONG_ARRAY_ID: u8 = 0x0C;

/// Maximum number of elements accepted when decoding a list or array.
pub const MAX_ARRAY_LENGTH: usize = 512_000;
/// Maximum nesting depth allowed when decoding NBT compound or list tags.
pub const MAX_NBT_DEPTH: usize = 512;

/// Errors produced while reading, writing, or converting NBT data.
#[derive(Error, Debug)]
pub enum Error {
    /// The root tag was not a compound tag and contains the reported tag ID.
    #[error("The root tag of the NBT file is not a compound tag. Received tag id: {0}")]
    NoRootCompound(u8),
    /// A tag ID not defined by the NBT format was encountered.
    #[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}")]

View on GitHub (pinned to 8d4639e25a)