{"record":{"id":"459096c01660794c","repo":"astral-sh/ruff","slug":"expected-to-handle-named-fields-459096","errorCode":null,"errorMessage":"Expected to handle named fields","messagePattern":"Expected to handle named fields","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff_macros/src/config.rs","lineNumber":112,"sourceCode":"                    #documentation\n                }\n            })\n        }\n        _ => Err(syn::Error::new(\n            ident.span(),\n            \"Can only derive ConfigurationOptions from structs with named fields.\",\n        )),\n    }\n}\n\n/// For a field with type `Option<Foobar>` where `Foobar` itself is a struct\n/// deriving `ConfigurationOptions`, create code that calls retrieves options\n/// from that group: `Foobar::get_available_options()`\nfn handle_option_group(field: &Field) -> syn::Result<proc_macro2::TokenStream> {\n    let ident = field\n        .ident\n        .as_ref()\n        .expect(\"Expected to handle named fields\");\n\n    match &field.ty {\n        Type::Path(TypePath {\n            path: Path { segments, .. },\n            ..\n        }) => match segments.first() {\n            Some(PathSegment {\n                ident: type_ident,\n                arguments:\n                    PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }),\n            }) if type_ident == \"Option\" => {\n                let path = &args[0];\n                let kebab_name = LitStr::new(&ident.to_string().replace('_', \"-\"), ident.span());\n\n                Ok(quote_spanned!(\n                    ident.span() => (visit.record_set(#kebab_name, ruff_options_metadata::OptionSet::of::<#path>()))\n                ))\n            }","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_macros/src/config.rs#L94-L130","documentation":"`handle_option_group` in the `ConfigurationOptions` derive walks the fields of a configuration group struct and reads each field's name via `field.ident`. Only named-field structs are supported, so a tuple or unit field makes `ident` `None` and the `.expect` panics at macro expansion time. It is invoked from `derive_impl` for each group-level field.","triggerScenarios":"Deriving `ConfigurationOptions` on a struct containing tuple fields (e.g. `struct GlobalOptions(Version)`) or unit fields, causing `field.ident.as_ref()` to be `None` during expansion.","commonSituations":"Adding a new group type to ty/ruff configuration as a new-type wrapper, or refactoring a named-field struct into tuple syntax while keeping the derive.","solutions":["Give the group struct named fields: `struct GlobalOptions { version: Version }`.","Drop the `ConfigurationOptions` derive from the offending type and implement `get_available_options` manually.","Patch `handle_option_group` in crates/ruff_macros/src/config.rs to return a spanned `syn::Error` for non-named fields rather than panicking."],"exampleFix":"// before\n#[derive(ConfigurationOptions)]\nstruct CacheOptions(PathBuf);\n\n// after\n#[derive(ConfigurationOptions)]\nstruct CacheOptions {\n    dir: PathBuf,\n}","handlingStrategy":"validation","validationCode":"// Ensure the group struct is named-field before deriving:\n// struct Group { version: Version }   // OK\n// struct Group(Version);              // panics the macro\n// Macro-side guard:\nlet Some(ident) = field.ident.as_ref() else {\n    return Err(syn::Error::new_spanned(field, \"option groups require named fields\"));\n};","typeGuard":"fn all_fields_named(data: &syn::Data) -> bool {\n    match data {\n        syn::Data::Struct(s) => s.fields.iter().all(|f| f.ident.is_some()),\n        _ => false,\n    }\n}","tryCatchPattern":null,"preventionTips":["Keep every `ConfigurationOptions` group struct named-field only.","Never use new-type wrappers for configuration groups.","Replace `.expect` in the derive with spanned syn errors.","Document the named-fields requirement on the derive macro."],"tags":["rust","proc-macro","configuration","named-fields"],"backgroundTag":"derive-macro-unsupported-field-shape","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}