cloudflare/quiche · error

value is too large for varint

Error message

value is too large for varint

What it means

octets panics in put_varint_with_len when the value to encode does not fit in the requested varint length. QUIC varints support 1/2/4/8-byte encodings with maxima of 63, 16383, 2^30-1, and 2^62-1; the panic arm is an internal exhaustive-match fallback reached only if the value exceeds even the 8-byte encoding (>= 2^62) or len was not one of the supported sizes. put_varint guarantees a valid len, so in practice only values >= 2^62 hit this.

Solutions

  1. Validate the value before encoding: ensure v < (1u64 << 62) (and fits the chosen len: <1<<6, <1<<14, <1<<30, <1<<62).
  2. Clamp or reject upstream values that can exceed the QUIC varint range instead of encoding them.
  3. If calling put_varint_with_len directly, restrict len to 1, 2, 4, or 8 and size it to the value.

Example fix

// before
b.put_varint(huge_value)?;
// after
assert!(huge_value < (1u64 << 62), "value too large for QUIC varint");
b.put_varint(huge_value)?;
Defensive patterns

Strategy: validation

Validate before calling

fn fits_varint(v: u64) -> bool { v < (1u64 << 62) }
// call site
assert!(fits_varint(v), "value {} exceeds QUIC varint range", v);

Prevention

When it happens

Trigger: Calling put_varint with a u64 >= 2^62 (the match falls through to the 8-branch otherwise), or calling put_varint_with_len directly with a length other than 1/2/4/8 combined with an out-of-range value.

Common situations: Encoding untrusted or corrupted counters (e.g. huge IDs, offsets, lengths parsed from bad input) into QUIC frames; math bugs producing u64::MAX-like values; fuzz-generated inputs.

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 cloudflare/quiche@9f96daa2c2 (2026-09-08). Data as JSON: /api/errors/b838990177c8fdc5. Report an issue: GitHub.

Appendix: source

Thrown at octets/src/lib.rs:579

            2 => {
                let buf = self.put_u16(v as u16)?;
                buf[0] |= 0x40;
                buf
            },

            4 => {
                let buf = self.put_u32(v as u32)?;
                buf[0] |= 0x80;
                buf
            },

            8 => {
                let buf = self.put_u64(v)?;
                buf[0] |= 0xc0;
                buf
            },

            _ => panic!("value is too large for varint"),
        };

        Ok(buf)
    }

    /// Reads `len` bytes from the current offset without copying and advances
    /// the buffer.
    pub fn get_bytes(&mut self, len: usize) -> Result<Octets<'_>> {
        if self.cap() < len {
            return Err(BufferTooShortError);
        }

        let out = Octets {
            buf: &self.buf[self.off..self.off + len],
            off: 0,
        };

        self.off += len;

View on GitHub (pinned to 9f96daa2c2)