pydantic/monty · error

Function not found

Error message

Function not found

What it means

`get_function` indexes the functions vec with `FunctionId` and panics if the id is out of bounds. `FunctionId`s are only ever produced by the same intern table, so this documents the invariant that a live `FunctionId` always has a matching entry.

Solutions

  1. Ensure `FunctionId` values are used only with the table that produced them.
  2. Verify version compatibility when deserializing compiled functions.
  3. Report as a bug if triggered within a single table's lifetime.

Example fix

// before
self.functions.get(id.index()).expect("Function not found")
// after
self.functions.get(id.index())
    .ok_or_else(|| InternalError::MissingFunction(id))?
Defensive patterns

Strategy: validation

Validate before calling

assert!(function_id.index() < table.function_count(), "FunctionId out of range");

Prevention

When it happens

Trigger: Calling `get_function` with a `FunctionId` whose index is >= `functions.len()` — e.g. an id from a different/dropped table, a corrupted id, or a deserialization bug.

Common situations: Mixing ids across two `InternTable` instances, loading bytecode compiled by an incompatible version, or heap corruption.

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

Appendix: source

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

    /// Looks up a long integer by its `LongIntId`.
    ///
    /// # Panics
    ///
    /// Panics if the `LongIntId` is invalid.
    #[inline]
    pub fn get_long_int(&self, id: LongIntId) -> &BigInt {
        self.long_ints[id.index()].value()
    }

    /// Lookup a function by its `FunctionId`
    ///
    /// # Panics
    ///
    /// Panics if the `FunctionId` is invalid.
    #[inline]
    pub fn get_function(&self, id: FunctionId) -> &Function {
        self.functions.get(id.index()).expect("Function not found")
    }

    /// Injects `fault` into the named function's metadata.
    #[cfg(feature = "test-hooks")]
    pub(crate) fn corrupt_function_metadata_for_tests(&mut self, name: &str, fault: FunctionMetadataFault) {
        let index = self
            .functions
            .iter()
            .position(|function| self.get_str(function.name.name_id) == name)
            .unwrap_or_else(|| panic!("test function '{name}' not found"));
        self.functions[index].corrupt_metadata_for_tests(fault);
    }

    /// Returns the Python hash for an interned string.
    ///
    /// Dispatches by id range:
    /// * ASCII (`id < 128`): looks up [`ASCII_HASHES`] (per-slot lazy);
    ///   computes via [`hash_python_str`] on first use of that byte.

View on GitHub (pinned to adc986b362)