pydantic/monty · critical

LongIntId overflow

Error message

LongIntId overflow

What it means

`InternTable::intern_long_int` converts the table's length to a `LongIntId` backed by a small unsigned integer; the `expect` panics if there are more interned big integers than the ID type can represent. This is an interpreter-internal invariant, not a catchable error: it only fires after ~4 billion distinct long-int literals are interned in one session.

Source

Thrown at crates/monty/src/intern.rs:1422

    /// builtin names before the runtime table is built.
    pub fn get_string_id_by_name(&self, s: &str) -> Option<StringId> {
        get_string_id_by_name(&self.string_map, s)
    }

    /// Interns bytes, returning its `BytesId`.
    ///
    /// Unlike interns, bytes are not deduplicated (bytes literals are rare).
    pub fn intern_bytes(&mut self, b: &[u8]) -> BytesId {
        let id = BytesId(self.bytes.len().try_into().expect("BytesId overflow"));
        self.bytes.push(WithHash::for_bytes(b.to_vec()));
        id
    }

    /// Interns a long integer, returning its `LongIntId`.
    ///
    /// Big integers are not deduplicated since literals exceeding i64 are rare.
    pub fn intern_long_int(&mut self, bi: BigInt) -> LongIntId {
        let id = LongIntId(self.long_ints.len().try_into().expect("LongIntId overflow"));
        self.long_ints.push(WithHash::for_long_int(bi));
        id
    }

    /// Looks up a string by its `StringId`.
    #[inline]
    pub fn get_str(&self, id: StringId) -> &str {
        get_str(&self.strings, id)
    }
}

/// Interns `s` into a `string_map`/`strings` pair, shared by [`InternerBuilder`]
/// and [`Interns`] so both tables allocate ids identically.
///
/// Single-ASCII and [`StaticStrings`] values resolve to their reserved ids
/// without touching the pool; everything else is deduplicated via `string_map`.
fn intern_str(string_map: &mut AHashMap<String, StringId>, strings: &mut Vec<WithHash<String>>, s: &str) -> StringId {
    if s.len() == 1 {

View on GitHub (pinned to adc986b362)

Solutions

  1. Check why so many long integers are being interned without table reuse; recycle or reset the InternTable per compilation unit.
  2. Verify the ID type width (e.g. widen `LongIntId` to u64) if your workload legitimately interns enormous numbers of values.
  3. Report as a bug if reached with a normal workload.

Example fix

// before
let id = LongIntId(self.long_ints.len().try_into().expect("LongIntId overflow"));
// after
let id = LongIntId(u32::try_from(self.long_ints.len()).map_err(|_| CompileError::TooManyInternedValues)?);
Defensive patterns

Strategy: validation

Validate before calling

assert!(intern_table.long_int_count() < u32::MAX as usize, "LongIntId space exhausted");

Prevention

When it happens

Trigger: Calling `intern_long_int` (directly or via compiling/executing code with huge numbers of distinct >i64 integer literals) when `long_ints.len()` exceeds `u32::MAX` (or the backing integer width).

Common situations: Practically only hit by generated code containing billions of unique big-int literals, or a bug in table reuse/clearing that lets the table grow unboundedly.

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 pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/5c0df0b9a9a23d5c. Report an issue: GitHub.