pydantic/monty · error

Invalid static string ID

Error message

Invalid static string ID

What it means

`get_str` resolves a `StringId` by first checking ASCII single-char strings, then interned strings, then static strings; `StaticStrings::from_string_id` panics if the ID falls in none of the three ranges. A `StringId` outside all valid ranges means heap/table corruption or a bogus ID was constructed.

Source

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

    } else if let Ok(ss) = StaticStrings::from_str(s) {
        Some(ss.into())
    } else {
        string_map.get(s).copied()
    }
}

/// Looks up a string by its `StringId`.
///
/// # Panics
///
/// Panics if the `StringId` is invalid - not from this interner or ascii chars or StaticStrings.
fn get_str(strings: &[WithHash<String>], id: StringId) -> &str {
    if let Some(ascii_str) = ASCII_STRS.get(id.index()) {
        ascii_str
    } else if let Some(intern_index) = id.index().checked_sub(INTERN_STRING_ID_OFFSET) {
        strings[intern_index].value()
    } else {
        let static_str = StaticStrings::from_string_id(id).expect("Invalid static string ID");
        static_str.into()
    }
}

/// Storage for interned strings, bytes, long integers and compiled functions.
///
/// This provides lookup by `StringId`, `BytesId`, `LongIntId` and `FunctionId` for interned literals and functions.
///
/// # Append-only ownership in the REPL
///
/// Ids are stable and only ever appended, so a REPL session never copies this
/// table: it hands it to each snippet via [`into_builder`](Self::into_builder)
/// (or extends it in place with [`intern`](Self::intern)) and takes the extended
/// table back afterwards — whether the snippet succeeded or not.
///
/// # Hash tables
///
/// Each entry in `strings`/`bytes`/`long_ints` is a [`WithHash`] pairing

View on GitHub (pinned to adc986b362)

Solutions

  1. Audit how the offending `StringId` was produced; check offset arithmetic against `INTERN_STRING_ID_OFFSET`/static ranges.
  2. If deserializing snapshots/bytecode, ensure the producer and consumer versions match.
  3. Report as an interpreter bug with the failing input.

Example fix

// before
let static_str = StaticStrings::from_string_id(id).expect("Invalid static string ID");
// after
let static_str = StaticStrings::from_string_id(id)
    .ok_or_else(|| InternalError::InvalidStringId(id))?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_string_id(id: u32, strings_len: usize) -> bool { id < ASCII_STRS_LEN || id >= INTERN_STRING_ID_OFFSET && (id as usize - INTERN_STRING_ID_OFFSET) < strings_len }

Prevention

When it happens

Trigger: Calling `get_str` with a `StringId` that is neither an ASCII id, an interned id (>= INTERN_STRING_ID_OFFSET within range), nor a valid `StaticStrings` variant.

Common situations: Only from interpreter bugs: corrupted serialized IDs, wrong offset arithmetic, or reading an ID from a snapshot compiled by an incompatible version.

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/3977a39cbc0e26e9. Report an issue: GitHub.