PyO3/pyo3 · error
no class given for Fn with a "self" receiver
Error message
no class given for Fn with a "self" receiver
What it means
Inside pyo3-macros-backend's method handling, FnType::self_arg requires the class name (cls) to build the receiver conversion for methods that take `self`. The expect panics when the caller supplied None for a method type that needs a self receiver. This is an internal API contract of the macro crate, not a message users normally see.
Source
Thrown at pyo3-macros-backend/src/method.rs:281
false
}
}
}
pub fn self_arg(
&self,
cls: Option<&syn::Type>,
error_mode: ExtractErrorMode,
self_conversion: SelfConversionPolicy,
class_method_receiver: ClassMethodReceiver,
holders: &mut Holders,
ctx: &Ctx,
) -> Option<TokenStream> {
let Ctx { pyo3_path, .. } = ctx;
match self {
FnType::Getter(st) | FnType::Setter(st) | FnType::Deleter(st) | FnType::Fn(st) => {
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(View on GitHub (pinned to ac9b6899d3)
Solutions
- Pass the enclosing class identifier (Some(cls)) when calling self_arg for any self-receiving method.
- Only call self_arg with None for FnType without a self receiver (e.g. associated/classmethod variants that don't need it).
- If you are not writing macro code, this indicates a pyo3 bug — report with a minimal repro.
Example fix
// before ftype.self_arg(cls=None, ...) // after ftype.self_arg(Some(ident_of_class), ...)
Defensive patterns
Strategy: validation
Validate before calling
// Internal callers: assert class context before generating self receiver assert!(cls.is_some(), "self-receiving methods require a class name");
Type guard
fn has_class_context(cls: &Option<syn::Ident>) -> bool { cls.is_some() } Prevention
- Always thread the enclosing #[pyclass] ident into method codegen.
- Only pass cls=None for method kinds without a self receiver.
- Write a unit test over each FnType variant when forking the macro backend.
When it happens
Trigger: Calling the internal FnType::self_arg API (e.g. from a custom proc macro reusing pyo3's method codegen) with cls = None while the FnType is Getter/Setter/Deleter/Fn — i.e. any method with a self receiver.
Common situations: Custom derive/attribute macros built on pyo3 internals forgetting to thread the enclosing class name; upstream pyo3 always passes Some(cls) from #[pyclass] expansion.
Related errors
- Named fields should have identifiers
- no class given for a class method
- 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/5009ec3c452bc6a3.
Report an issue: GitHub.