{"record":{"id":"49db261094f6afee","repo":"pydantic/monty","slug":"cannot-get-type-of-undefined-value","errorCode":null,"errorMessage":"Cannot get type of undefined value","messagePattern":"Cannot get type of undefined value","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/monty/src/value.rs","lineNumber":248,"sourceCode":"    }\n}\n\nimpl From<bool> for Value {\n    fn from(v: bool) -> Self {\n        Self::Bool(v)\n    }\n}\n\nimpl<'h> PyTrait<'h> for Value {\n    /// Forwards to the inherent [`Value::py_type_name`], so generic `PyTrait`\n    /// callers also see the real class name of a named tuple or host instance.\n    fn py_type_name(&self, vm: &VM<'h>) -> Cow<'h, str> {\n        Self::py_type_name(self, vm)\n    }\n\n    fn py_type(&self, vm: &VM<'_>) -> Type {\n        match self {\n            Self::Undefined => panic!(\"Cannot get type of undefined value\"),\n            Self::Ellipsis => Type::Ellipsis,\n            Self::NotImplemented => Type::NotImplementedType,\n            Self::None => Type::NoneType,\n            Self::Bool(_) => Type::Bool,\n            Self::Int(_) | Self::InternLongInt(_) => Type::Int,\n            Self::Float(_) => Type::Float,\n            Self::InternString(_) => Type::Str,\n            Self::InternBytes(_) => Type::Bytes,\n            Self::Builtin(c) => c.py_type(),\n            Self::ModuleFunction(_) => Type::BuiltinFunction,\n            Self::DefFunction(_) => Type::Function,\n            Self::Marker(m) => m.py_type(),\n            Self::Property(_) => Type::Property,\n            Self::Ref(id) => vm.heap.read(*id).py_type(vm),\n            #[cfg(feature = \"memory-model-checks\")]\n            Self::Dereferenced => panic!(\"Cannot access Dereferenced object\"),\n        }\n    }","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty/src/value.rs#L230-L266","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the Undefined value at its origin and raise the proper Python error (e.g. NameError) instead of passing it on.","Match on `Value::Undefined` and handle it explicitly before any `py_type` call in the new code path.","Search for other conversion points (`convert_value`, isinstance helpers) to see how they guard Undefined and follow that pattern."],"exampleFix":"// before\nlet ty = value.py_type(vm); // panics if value is Undefined\n// after\nif matches!(value, Value::Undefined) {\n    return Err(vm.name_error(\"name is not defined\"));\n}\nlet ty = value.py_type(vm);","handlingStrategy":"type-guard","validationCode":"// Before calling type-taking APIs, ensure the value is defined:\n// if name_lookup(...) returned Undefined, raise NameError instead of proceeding.","typeGuard":"fn is_defined(v: &Value) -> bool {\n    !matches!(v, Value::Undefined)\n}","tryCatchPattern":"// Rust-side guard before py_type\nif matches!(value, Value::Undefined) {\n    return Err(ExcType::name_error(\"name is not defined\"));\n}\nlet ty = value.py_type(vm);","preventionTips":["Convert Undefined lookups into NameError at the lookup boundary, never propagate the sentinel.","Grep new code paths for py_type/py_type_name callers and verify their Undefined handling.","Add test cases for missing-name lookups through new APIs."],"tags":["rust","internal-error","panic","undefined-value","type-system"],"backgroundTag":"internal-invariant-violation","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}