PyO3/pyo3 · critical
failed to create type object for
Error message
failed to create type object for `{type_name}` What it means
type_object_init_failed is called from pyclass_type_object_raw when creating a #[pyclass]'s type object fails (e.g. during lazy type object initialization). It writes the underlying PyErr as unraisable and then panics, since the type object can never be produced.
Solutions
- Inspect the unraisable PyErr printed to stderr just before the panic — it names the real cause
- Ensure the pyclass is registered/initialized in a healthy interpreter context (correct module init, not during finalization)
- Fix pyclass definition issues: conflicting names, invalid base classes, or misconfigured #[pyclass(...)] options
Defensive patterns
Strategy: try-catch
Validate before calling
// register classes only during module init, while the interpreter is healthy
#[pymodule]
fn mymod(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<MyClass>()?;
Ok(())
} Try / catch
// capture the unraisable cause before the abort by installing a hook in tests
Python::with_gil(|py| unsafe {
ffi::PyErr_SetInterrupt /* or run under a test harness that reads unraisable output */;
}); Prevention
- Only create/access pyclass type objects during normal module initialization
- Read the unraisable PyErr printed before the panic to find the root cause
- Avoid duplicate class names and invalid base classes in #[pyclass] definitions
When it happens
Trigger: First access to a #[pyclass] type object when PyType creation fails — usually because __new__/base class setup failed, module registration context is invalid, or the interpreter is in an error/initialization-failure state.
Common situations: Using a pyclass before/beyond a valid module init; interpreter shutdown while creating the type; invalid pyclass attributes (bad base, duplicate name) surfacing as PyErr at type creation.
Related errors
- 0 < N <= 12
- Attaching a thread to the interpreter is currently…
- Attaching a thread to the interpreter is prohibited while a…
- attempted to fetch exception but none was set
- Cannot attach to the Python interpreter while it is…
AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05).
Data as JSON: /api/errors/ff1936280318954d.
Report an issue: GitHub.
Appendix: source
Thrown at src/impl_/pyclass/lazy_type_object.rs:260
) -> PyResult<()> {
// We hold the GIL: the dictionary update can be considered atomic from
// the POV of other threads.
for (key, val) in items {
crate::err::error_on_minusone(py, unsafe {
ffi::PyObject_SetAttrString(type_object, key.as_ptr(), val.as_ptr())
})?;
}
Ok(())
}
// This is necessary for making static `LazyTypeObject`s
unsafe impl<T> Sync for LazyTypeObject<T> {}
/// Used in the macro-expanded implementation of `type_object_raw` for `#[pyclass]` types
#[cold]
pub fn type_object_init_failed(py: Python<'_>, err: PyErr, type_name: &str) -> ! {
err.write_unraisable(py, None);
panic!("failed to create type object for `{type_name}`")
}
/// The full macro-expanded implementation of `type_object_raw` for `#[pyclass]` types, kept
/// out-of-line here to reduce the amount of macro-generated code.
#[inline]
pub fn pyclass_type_object_raw<T: PyClass>(py: Python<'_>) -> *mut ffi::PyTypeObject {
use crate::types::PyTypeMethods;
T::lazy_type_object()
.get_or_try_init(py)
.unwrap_or_else(|e| type_object_init_failed(py, e, <T as PyClass>::NAME))
.as_type_ptr()
}
#[cold]
fn wrap_in_runtime_error(py: Python<'_>, err: PyErr, message: String) -> PyErr {
let runtime_err = PyRuntimeError::new_err(message);
runtime_err.set_cause(py, Some(err));
runtime_errView on GitHub (pinned to ac9b6899d3)