GitoxideLabs/gitoxide · error

entry header size does not fit into u16

Error message

entry header size does not fit into u16

What it means

When decoding a pack entry header, the number of bytes consumed by the header is stored as u16 (`encoded_header_size`). If the header consumed more than 65535 bytes, the try_into conversion fails with Error::Corrupt, surfaced as an io::Error of kind InvalidData with 'entry header size does not fit into u16'. This indicates a malformed or absurdly large pack entry header.

Solutions

  1. Re-obtain the pack file: re-clone or re-fetch the repository
  2. Verify the pack with `gix pack verify` to confirm corruption
  3. Check that the pack file was not modified in transit (compare checksums)
  4. If it occurs during fuzz/testing, treat it as an expected rejection of invalid input
Defensive patterns

Strategy: validation

Validate before calling

// validate pack before parsing entries
gix::pack::data::verify_integrity(pack_reader, progress, interrupt)
    .map_err(|e| format!("pack corrupt: {e}"))?;

Prevention

When it happens

Trigger: Parsing a pack entry whose variable-length (LEB128-style) header spans more than u16::MAX bytes — only possible with a deliberately corrupt or crafted pack stream.

Common situations: Reading a maliciously crafted or bit-rotted pack file; fuzzing inputs; corrupted downloads.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/216b8de515525e9a. Report an issue: GitHub.

Appendix: source

Thrown at gix-pack/src/data/entry/decode.rs:101

                r.read_exact(hash)?;
                let delta = RefDelta {
                    base_id: gix_hash::ObjectId::from_bytes_or_panic(&hash[..]),
                };
                consumed += hash_len;
                delta
            }
            BLOB => Blob,
            TREE => Tree,
            COMMIT => Commit,
            TAG => Tag,
            other => return Err(io::Error::other(format!("Object type {other} is unsupported"))),
        };
        Ok(data::Entry {
            header: object,
            decompressed_size: size,
            data_offset: pack_offset + consumed as u64,
            encoded_header_size: encoded_header_size(consumed)
                .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?,
        })
    }
}

fn encoded_header_size(consumed: usize) -> Result<u16, Error> {
    consumed.try_into().map_err(|_| Error::Corrupt {
        message: "entry header size does not fit into u16",
    })
}

#[inline]
fn streaming_parse_header_info(read: &mut dyn io::Read) -> Result<(u8, u64, usize), io::Error> {
    let mut byte = [0u8; 1];
    read.read_exact(&mut byte)?;
    let mut c = byte[0];
    let mut i = 1;
    let type_id = (c >> 4) & 0b0000_0111;
    let mut size = u64::from(c) & 0b0000_1111;

View on GitHub (pinned to e73179060b)