{"record":{"id":"887be06314c2edf4","repo":"PyO3/pyo3","slug":"named-fields-should-have-identifiers-887be0","errorCode":null,"errorMessage":"Named fields should have identifiers","messagePattern":"Named fields should have identifiers","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pyo3-macros-backend/src/intopyobject.rs","lineNumber":154,"sourceCode":"                    );\n                    ensure_spanned!(\n                        options.rename_all.is_none(),\n                        options.rename_all.span() => \"`rename_all` is not permitted on `transparent` structs and variants\"\n                    );\n                    ensure_spanned!(\n                        attrs.into_py_with.is_none(),\n                        attrs.into_py_with.span() => \"`into_py_with` is not permitted on `transparent` structs or variants\"\n                    );\n                    ContainerType::StructNewtype(field)\n                } else {\n                    let struct_fields = named\n                        .named\n                        .iter()\n                        .map(|field| {\n                            let ident = field\n                                .ident\n                                .as_ref()\n                                .expect(\"Named fields should have identifiers\");\n\n                            let attrs = FieldAttributes::from_attrs(&field.attrs)?;\n\n                            Ok(NamedStructField {\n                                ident,\n                                field,\n                                item: attrs.getter.and_then(|getter| match getter {\n                                    crate::derive_attributes::FieldGetter::GetItem(_, lit) => {\n                                        Some(ItemOption(lit))\n                                    }\n                                    crate::derive_attributes::FieldGetter::GetAttr(_, _) => None,\n                                }),\n                                into_py_with: attrs.into_py_with,\n                            })\n                        })\n                        .collect::<Result<Vec<_>>>()?;\n                    ContainerType::Struct(struct_fields)\n                }","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/pyo3-macros-backend/src/intopyobject.rs#L136-L172","documentation":"This is an internal invariant panic in PyO3's #[pyclass]/derive proc-macro backend. When processing a struct with named fields, the macro unwraps each field's identifier via Option::expect. Syn guarantees that fields inside syn::Fields::Named always carry an identifier, so this panic indicates the macro was invoked on a malformed or mutated AST rather than anything a normal user can trigger.","triggerScenarios":"Only reachable if the syn AST is corrupted or a fork/plugins passes unnamed fields where named fields are expected; not reachable from ordinary #[derive(IntoPyObject)] / #[pyclass] usage on a valid struct.","commonSituations":"Practically never seen by end users; may surface when pinning an unusual syn version, using a fork of pyo3-macros-backend, or writing a custom derive that reuses PyO3's internal APIs.","solutions":["Verify you are using an unmodified, compatible pyo3 version (pyo3 and pyo3-macros-backend from the same release).","Check that the derive input is a normal struct with named fields (no tuple/unit struct passed where named-field handling runs).","If you reuse pyo3 macro internals, ensure you only call this path with syn::Fields::Named input.","File a minimal reproduction against pyo3 if the panic occurs with valid code."],"exampleFix":"// before (struct that confuses the macro path)\n#[derive(IntoPyObject)]\nstruct MyStruct(u32);\n// after (named-field struct)\n#[derive(IntoPyObject)]\nstruct MyStruct { value: u32 }","handlingStrategy":"validation","validationCode":"// Ensure the derive input is a named-field struct\nmatch &input.data {\n    syn::Data::Struct(s) => matches!(s.fields, syn::Fields::Named(_)),\n    _ => false,\n};","typeGuard":"fn is_named_field_struct(item: &syn::Item) -> bool {\n    matches!(&item.data, syn::Data::Struct(s) if matches!(s.fields, syn::Fields::Named(_)))\n}","tryCatchPattern":null,"preventionTips":["Keep pyo3 and pyo3-macros-backend versions in lockstep (same crate release).","Only apply the derive to plain named-field structs.","Avoid forks/patches of the macro backend unless you understand its invariants."],"tags":["pyo3","proc-macro","panic","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"}