{"record":{"id":"5009ec3c452bc6a3","repo":"PyO3/pyo3","slug":"no-class-given-for-fn-with-a-self-receiver","errorCode":null,"errorMessage":"no class given for Fn with a \"self\" receiver","messagePattern":"no class given for Fn with a \"self\" receiver","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pyo3-macros-backend/src/method.rs","lineNumber":281,"sourceCode":"                false\n            }\n        }\n    }\n\n    pub fn self_arg(\n        &self,\n        cls: Option<&syn::Type>,\n        error_mode: ExtractErrorMode,\n        self_conversion: SelfConversionPolicy,\n        class_method_receiver: ClassMethodReceiver,\n        holders: &mut Holders,\n        ctx: &Ctx,\n    ) -> Option<TokenStream> {\n        let Ctx { pyo3_path, .. } = ctx;\n        match self {\n            FnType::Getter(st) | FnType::Setter(st) | FnType::Deleter(st) | FnType::Fn(st) => {\n                Some(st.receiver(\n                    cls.expect(\"no class given for Fn with a \\\"self\\\" receiver\"),\n                    error_mode,\n                    self_conversion,\n                    holders,\n                    ctx,\n                ))\n            }\n            FnType::FnClass(span) => {\n                let py = syn::Ident::new(\"py\", Span::call_site());\n                let slf: Ident = syn::Ident::new(\"_slf\", Span::call_site());\n                let pyo3_path = pyo3_path.to_tokens_spanned(*span);\n                let class_method_receiver = match class_method_receiver {\n                    ClassMethodReceiver::Class => quote! { #slf.cast() },\n                    ClassMethodReceiver::Instance => {\n                        let type_check = match self_conversion.0 {\n                            SelfConversionPolicyInner::Trusted => quote! {},\n                            SelfConversionPolicyInner::Checked => {\n                                let cls = cls.expect(\"no class given for a class method\");\n                                let type_check = error_mode.handle_error(","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/pyo3-macros-backend/src/method.rs#L263-L299","documentation":"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.","triggerScenarios":"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.","commonSituations":"Custom derive/attribute macros built on pyo3 internals forgetting to thread the enclosing class name; upstream pyo3 always passes Some(cls) from #[pyclass] expansion.","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."],"exampleFix":"// before\nftype.self_arg(cls=None, ...)\n// after\nftype.self_arg(Some(ident_of_class), ...)","handlingStrategy":"validation","validationCode":"// Internal callers: assert class context before generating self receiver\nassert!(cls.is_some(), \"self-receiving methods require a class name\");","typeGuard":"fn has_class_context(cls: &Option<syn::Ident>) -> bool { cls.is_some() }","tryCatchPattern":null,"preventionTips":["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."],"tags":["pyo3","proc-macro","method-generation","internal-invariant"],"backgroundTag":"internal-invariant-panic","analyzedSha":"ac9b6899d348be4d54614d060dea53a645a12e36","analyzedAt":"2026-09-05T09:20:35.319Z","contentChangedAt":"2026-09-05T09:20:35.319Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}