pydantic/monty · error

Cannot get type of undefined value

Error message

Cannot get type of undefined value

What it means

Monty panics when `py_type()` is called on the `Value::Undefined` variant, which by design has no Python type. `Undefined` is an internal sentinel (e.g. for missing lookups); reaching `py_type` on it means an undefined value leaked into a path that should have produced a proper Python error (like a NameError) beforehand. Callers include isinstance checks, type(), class creation, and exception matching.

Source

Thrown at crates/monty/src/value.rs:248

    }
}

impl From<bool> for Value {
    fn from(v: bool) -> Self {
        Self::Bool(v)
    }
}

impl<'h> PyTrait<'h> for Value {
    /// Forwards to the inherent [`Value::py_type_name`], so generic `PyTrait`
    /// callers also see the real class name of a named tuple or host instance.
    fn py_type_name(&self, vm: &VM<'h>) -> Cow<'h, str> {
        Self::py_type_name(self, vm)
    }

    fn py_type(&self, vm: &VM<'_>) -> Type {
        match self {
            Self::Undefined => panic!("Cannot get type of undefined value"),
            Self::Ellipsis => Type::Ellipsis,
            Self::NotImplemented => Type::NotImplementedType,
            Self::None => Type::NoneType,
            Self::Bool(_) => Type::Bool,
            Self::Int(_) | Self::InternLongInt(_) => Type::Int,
            Self::Float(_) => Type::Float,
            Self::InternString(_) => Type::Str,
            Self::InternBytes(_) => Type::Bytes,
            Self::Builtin(c) => c.py_type(),
            Self::ModuleFunction(_) => Type::BuiltinFunction,
            Self::DefFunction(_) => Type::Function,
            Self::Marker(m) => m.py_type(),
            Self::Property(_) => Type::Property,
            Self::Ref(id) => vm.heap.read(*id).py_type(vm),
            #[cfg(feature = "memory-model-checks")]
            Self::Dereferenced => panic!("Cannot access Dereferenced object"),
        }
    }

View on GitHub (pinned to adc986b362)

Solutions

  1. Check the Undefined value at its origin and raise the proper Python error (e.g. NameError) instead of passing it on.
  2. Match on `Value::Undefined` and handle it explicitly before any `py_type` call in the new code path.
  3. Search for other conversion points (`convert_value`, isinstance helpers) to see how they guard Undefined and follow that pattern.

Example fix

// before
let ty = value.py_type(vm); // panics if value is Undefined
// after
if matches!(value, Value::Undefined) {
    return Err(vm.name_error("name is not defined"));
}
let ty = value.py_type(vm);
Defensive patterns

Strategy: type-guard

Validate before calling

// Before calling type-taking APIs, ensure the value is defined:
// if name_lookup(...) returned Undefined, raise NameError instead of proceeding.

Type guard

fn is_defined(v: &Value) -> bool {
    !matches!(v, Value::Undefined)
}

Try / catch

// Rust-side guard before py_type
if matches!(value, Value::Undefined) {
    return Err(ExcType::name_error("name is not defined"));
}
let ty = value.py_type(vm);

Prevention

When it happens

Trigger: Any code path that obtains a `Value::Undefined` (e.g. a failed name/builtin lookup returning Undefined) and then calls `py_type`, `isinstance`, `type()`, `issubclass`, or exception matching on it instead of converting it to a NameError first.

Common situations: Hit by Monty contributors adding new name-lookup or attribute paths that propagate Undefined too far, or by bindings (PyO3/napi) converting values without checking for Undefined.

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