GraphiteEditor/Graphite · error · syn::Error
ExtractField only works on structs with named fields
Error message
ExtractField only works on structs with named fields
What it means
The `ExtractField` derive only supports structs with named fields because it generates a `field_types()` introspection listing each field's name, type, and source line (used for editor message documentation). Tuple structs and unit structs have no field names to report, so the derive aborts with this compile-time error.
Source
Thrown at proc-macros/src/extract_fields.rs:17
use crate::helpers::clean_rust_type_syntax;
use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, format_ident, quote};
use syn::{Data, DeriveInput, Fields, Type, parse2};
pub fn derive_extract_field_impl(input: TokenStream) -> syn::Result<TokenStream> {
let input = parse2::<DeriveInput>(input)?;
let struct_name = &input.ident;
let generics = &input.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let line_number = struct_name.span().start().line;
let fields = match &input.data {
Data::Struct(data) => match &data.fields {
Fields::Named(fields) => &fields.named,
_ => return Err(syn::Error::new(Span::call_site(), "ExtractField only works on structs with named fields")),
},
_ => return Err(syn::Error::new(Span::call_site(), "ExtractField only works on structs")),
};
let mut field_line = Vec::new();
// Extract field names and types as strings at compile time
let field_info = fields
.iter()
.map(|field| {
let ident = field.ident.as_ref().unwrap();
let name = ident.to_string();
let ty = clean_rust_type_syntax(field.ty.to_token_stream().to_string());
let line = ident.span().start().line;
field_line.push(line);
(name, ty)
})
.collect::<Vec<_>>();
View on GitHub (pinned to c507b35645)
Solutions
- Convert the tuple struct to named fields: `struct Foo { value: u32, name: String }`.
- If the type must stay a tuple struct, remove `ExtractField` from its derive list.
- For unit structs, remove the derive — there are no fields to extract.
Example fix
// before
#[derive(ExtractField)]
struct LayerSnapshot(u64, String);
// after
#[derive(ExtractField)]
struct LayerSnapshot {
id: u64,
name: String,
} Defensive patterns
Strategy: validation
Prevention
- Only derive ExtractField on structs with named fields.
- Prefer named-field structs for types that feed the editor message-doc pipeline.
- Grep for tuple structs before adding the derive: `rg '#[derive(.*ExtractField' -A2`.
When it happens
Trigger: Applying `#[derive(ExtractField)]` to a tuple struct (`struct Foo(u32, String);`) or a unit struct (`struct Marker;`). Only `Fields::Named` is accepted.
Common situations: Adding the derive to a newtype wrapper or marker type during a refactor, or applying a blanket `#[derive(Debug, Clone, ExtractField)]` via editor tooling/templating without checking the struct shape.
Related errors
- The `{variant_type}` message should be defined as a struct-s
- Tried to derive AsMessage for non-enum
- Tried to derive a discriminant for non-enum
- ExtractField only works on structs
- Tried to derive HierarchicalTree for non-enum
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/f6ca8804523dacb2.
Report an issue: GitHub.