PyO3/pyo3 · error
no class given for a class method
Error message
no class given for a class method
What it means
When generating code for a #[classmethod]-style method, PyO3 checks the `cls` (self) argument. With the default Checked self-conversion policy it must know the target class to emit a Bound::ref_from_ptr(...).cast::<Cls>() type check; the expect panics if no class was provided. Like error 72, this guards pyo3-macros-backend's internal API contract.
Source
Thrown at pyo3-macros-backend/src/method.rs:298
Some(st.receiver(
cls.expect("no class given for Fn with a \"self\" receiver"),
error_mode,
self_conversion,
holders,
ctx,
))
}
FnType::FnClass(span) => {
let py = syn::Ident::new("py", Span::call_site());
let slf: Ident = syn::Ident::new("_slf", Span::call_site());
let pyo3_path = pyo3_path.to_tokens_spanned(*span);
let class_method_receiver = match class_method_receiver {
ClassMethodReceiver::Class => quote! { #slf.cast() },
ClassMethodReceiver::Instance => {
let type_check = match self_conversion.0 {
SelfConversionPolicyInner::Trusted => quote! {},
SelfConversionPolicyInner::Checked => {
let cls = cls.expect("no class given for a class method");
let type_check = error_mode.handle_error(
quote_spanned! { *span =>
#pyo3_path::Bound::ref_from_ptr(#py, &#slf).cast::<#cls>()
},
ctx,
);
quote! { #type_check; }
}
};
quote! {{
#type_check
#pyo3_path::ffi::Py_TYPE(#slf).cast()
}}
}
};
let ret = quote_spanned! { *span =>
#[allow(clippy::useless_conversion, reason = "#[classmethod] accepts anything which implements `From<&Bound<PyType>>`")]
::core::convert::Into::into(View on GitHub (pinned to ac9b6899d3)
Solutions
- Supply Some(cls) when generating a class method's self argument.
- Alternatively mark the conversion as Trusted only if you can guarantee the pointer is the right type (unsafe; avoid).
- Report to pyo3 if triggered by stock macros with valid code.
Example fix
// before self_arg(None) // for a #[classmethod] with default (checked) conversion // after self_arg(Some(class_ident))
Defensive patterns
Strategy: validation
Validate before calling
// Class methods with Checked conversion need cls
if policy == Checked { assert!(cls.is_some(), "class method requires cls"); } Type guard
fn classmethod_ok(cls: &Option<syn::Ident>, trusted: bool) -> bool {
trusted || cls.is_some()
} Prevention
- Never generate #[classmethod] code without the class identifier.
- Avoid switching to Trusted conversion just to skip the check — it removes type safety.
- Test generated classmethods in CI when patching macro internals.
When it happens
Trigger: Invoking the internal FnType::self_arg with cls = None for a class method whose SelfConversionPolicy is Checked (the default); i.e. class methods must always receive their class name.
Common situations: Hand-rolled macros or codegen tools reusing pyo3 method internals and omitting the class context; not reachable through normal #[pyclass] / #[classmethod] usage.
Related errors
- Named fields should have identifiers
- no class given for Fn with a "self" receiver
- complex enum has a non-unit variant
- named field has an identifier
- should always have positional defaults <= positional paramet
AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05).
Data as JSON: /api/errors/d56ec8f5bd7f3a2b.
Report an issue: GitHub.