PyO3/pyo3 · error
named field has an identifier
Error message
named field has an identifier
What it means
When extracting named fields of a #[pyclass] enum variant, the macro unwraps each field's identifier with expect. As with struct fields, syn guarantees named fields carry identifiers, so this panic signals a corrupted AST or wrong code path (e.g. tuple/unit variants reaching the named-field branch).
Source
Thrown at pyo3-macros-backend/src/pyclass.rs:699
|variant: &'a mut syn::Variant| -> syn::Result<PyClassEnumVariant<'a>> {
use syn::Fields;
let ident = &variant.ident;
let options = EnumVariantPyO3Options::take_pyo3_options(&mut variant.attrs)?;
let variant = match &variant.fields {
Fields::Unit => {
bail_spanned!(variant.span() => format!(
"Unit variant `{ident}` is not yet supported in a complex enum\n\
= help: change to an empty tuple variant instead: `{ident}()`\n\
= note: the enum is complex because of non-unit variant `{witness}`",
ident=ident, witness=witness))
}
Fields::Named(fields) => {
let fields = fields
.named
.iter()
.map(|field| PyClassEnumVariantNamedField {
ident: field.ident.as_ref().expect("named field has an identifier"),
ty: &field.ty,
attrs: &field.attrs,
span: field.span(),
})
.collect();
PyClassEnumVariant::Struct(PyClassEnumStructVariant {
ident,
fields,
options,
attrs: variant.attrs.clone(),
})
}
Fields::Unnamed(types) => {
let fields = types
.unnamed
.iter()
.map(|field| PyClassEnumVariantUnnamedField {View on GitHub (pinned to ac9b6899d3)
Solutions
- Use an unmodified pyo3/syn combination from the same supported versions.
- Ensure any intervening macro passes preserve field identifiers on named fields.
- Route non-named variants to their proper match arms before this code runs.
- Report a minimal repro to pyo3 if valid code panics.
Example fix
// before (variant reaching the wrong branch)
enum E { Tuple(u32) } // processed as named-fields
// after
enum E { Struct { value: u32 } } // matches Fields::Named branch Defensive patterns
Strategy: validation
Validate before calling
// Only route Fields::Named variants through the named-field extractor matches!(variant.fields, syn::Fields::Named(_));
Type guard
fn has_named_fields(v: &syn::Variant) -> bool {
matches!(v.fields, syn::Fields::Named(_))
} Prevention
- Match all three syn::Fields arms explicitly in enum-variant handling.
- Preserve field identifiers in any AST-rewriting passes that run before pyo3.
- Pin a supported syn version compatible with your pyo3 release.
When it happens
Trigger: Internal path violation: a variant with tuple or unit fields processed by the Fields::Named branch; not triggerable from valid user code with #[pyclass] enums.
Common situations: Patched macro backends, syn version mismatches, or third-party attribute macros that rewrite variant fields before pyo3 sees them.
Related errors
- complex enum has a non-unit variant
- Named fields should have identifiers
- Empty enum
- no class given for Fn with a "self" receiver
- no class given for a class method
AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05).
Data as JSON: /api/errors/788b874fc063e93c.
Report an issue: GitHub.