PyO3/pyo3 · error

Named fields should have identifiers

Error message

Named fields should have identifiers

What it means

When building FromPyObject extraction for a struct with named fields, pyo3 expects each syn::Field in a named-fields struct to have an identifier. `field.ident` is None only for tuple-variant fields, so encountering None here is an internal invariant violation and panics with 'Named fields should have identifiers'.

Source

Thrown at pyo3-macros-backend/src/frompyobject.rs:212

                    let field = tuple_fields.pop().unwrap();
                    ContainerType::TupleNewtype(field.from_py_with, Box::new(field.ty))
                } else if options.transparent.is_some() {
                    bail_spanned!(
                        fields.span() => "transparent structs and variants can only have 1 field"
                    );
                } else {
                    ContainerType::Tuple(tuple_fields)
                }
            }
            Fields::Named(named) if !named.named.is_empty() => {
                let mut struct_fields = named
                    .named
                    .iter()
                    .map(|field| {
                        let ident = field
                            .ident
                            .as_ref()
                            .expect("Named fields should have identifiers");
                        let mut attrs = FieldAttributes::from_attrs(&field.attrs)?;

                        if let Some(ref from_item_all) = options.from_item_all {
                            if let Some(replaced) = attrs.getter.replace(FieldGetter::GetItem(parse_quote!(item), None))
                            {
                                match replaced {
                                    FieldGetter::GetItem(item, Some(item_name)) => {
                                        attrs.getter = Some(FieldGetter::GetItem(item, Some(item_name)));
                                    }
                                    FieldGetter::GetItem(_, None) => bail_spanned!(from_item_all.span() => "Useless `item` - the struct is already annotated with `from_item_all`"),
                                    FieldGetter::GetAttr(_, _) => bail_spanned!(
                                        from_item_all.span() => "The struct is already annotated with `from_item_all`, `attribute` is not allowed"
                                    ),
                                }
                            }
                        }

                        Ok(NamedStructField {

View on GitHub (pinned to ac9b6899d3)

Solutions

  1. Check you're deriving FromPyObject on a struct/variant with named fields, not a tuple or unit variant
  2. Use the appropriate derive/impl path for tuple structs (positional extraction)
  3. Update pyo3 — if this panics on valid named-field input it's a macro bug worth reporting

Example fix

// before
#[derive(FromPyObject)]
struct Point(f64, f64); // tuple struct hitting named-field path
// after
#[derive(FromPyObject)]
struct Point { x: f64, y: f64 }
Defensive patterns

Strategy: validation

Validate before calling

// ensure derived items use named fields for the named-field path
match data {
    syn::Data::Struct(d) if matches!(d.fields, syn::Fields::Named(_)) => Ok(()),
    _ => Err("named-field derive requires named fields".into()),
}

Prevention

When it happens

Trigger: Deriving FromPyObject on data where the code path for named fields receives an unnamed (tuple) field — typically a bug in the derive internals or mismatched variant/field handling, e.g. a unit or tuple variant routed through the named-field branch.

Common situations: Using pyo3 derive macros on unusual shape definitions (tuple structs handled by the wrong branch); bugs in macro-generated code; version-specific derive bugs.

Related errors


AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05). Data as JSON: /api/errors/210835e83973fb1a. Report an issue: GitHub.