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`] pairingView on GitHub (pinned to adc986b362)
Solutions
- Audit how the offending `StringId` was produced; check offset arithmetic against `INTERN_STRING_ID_OFFSET`/static ranges.
- If deserializing snapshots/bytecode, ensure the producer and consumer versions match.
- 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
- Never construct StringId outside intern.rs
- Match interpreter versions when sharing compiled artifacts
- Validate ids after deserialization
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
- LongIntId overflow
- StringId overflow
- StringId overflow while building reverse interns map
- dict_keys view must reference a dict
- dict_items view must always reference a dict
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/3977a39cbc0e26e9.
Report an issue: GitHub.