{"record":{"id":"0387e34039e004ce","repo":"BoundaryML/baml","slug":"bamlserde-cannot-be-derived-for-structs-use-serde-flatten-on","errorCode":null,"errorMessage":"BamlSerde cannot be derived for structs, use `#[serde(flatten)]` on dynamic instead.","messagePattern":"BamlSerde cannot be derived for structs, use `#\\[serde\\(flatten\\)\\]` on dynamic instead\\.","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"languages/rust/baml-macros/src/baml_serde.rs","lineNumber":11,"sourceCode":"use proc_macro2::{Span, TokenStream};\nuse quote::quote;\nuse syn::{Data, DataEnum, DeriveInput, Ident, Result};\n\nuse crate::shared::{ContainerAttrs, VariantAttrs};\n\npub(crate) fn derive_serde(input: &DeriveInput) -> Result<TokenStream> {\n    let container_attrs = ContainerAttrs::from_attrs(&input.attrs)?;\n\n    match &input.data {\n        Data::Struct(..) => Err(syn::Error::new(\n            Span::call_site(),\n            \"BamlSerde cannot be derived for structs, use `#[serde(flatten)]` on dynamic instead.\",\n        )),\n        Data::Enum(data_enum) if container_attrs.union => {\n            derive_serde_union(data_enum, &input.ident)\n        }\n        Data::Enum(..) => Err(syn::Error::new(\n            Span::call_site(),\n            \"BamlSerde cannot be derived for enums, use `#[serde(untagged)]` on dynamic instead.\",\n        )),\n        Data::Union(..) => Err(syn::Error::new(\n            Span::call_site(),\n            \"Rust unions are not supported for this derive macro.\",\n        )),\n    }\n}\n\nfn derive_serde_union(data: &DataEnum, ident: &Ident) -> Result<TokenStream> {","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/languages/rust/baml-macros/src/baml_serde.rs#L1-L29","documentation":"Compile-time error from the `BamlSerde` derive macro: it does not support Rust structs. For struct-shaped data the library requires a `dynamic` field marked with `#[serde(flatten)]` so unstructured data is captured there. This is emitted in `derive_serde` when the input is `Data::Struct`.","triggerScenarios":"Applying `#[derive(BamlSerde)]` to a struct definition, e.g. `#[derive(BamlSerde)] struct Foo { ... }`.","commonSituations":"Developers assuming BamlSerde works like plain serde derive on structs; converting an existing serde struct to use BamlSerde without reading the union/dynamic requirements.","solutions":["Add a `dynamic` field annotated with `#[serde(flatten)]` to capture extra data","Remove `BamlSerde` from the struct and use plain `serde` derives instead","Convert the struct to an enum if it is meant to be a BAML union (with `union = true` container attr)"],"exampleFix":"// before\n#[derive(BamlSerde)]\nstruct Foo { a: i32 }\n// after\n#[derive(BamlSerde)]\nstruct Foo { a: i32, #[serde(flatten)] dynamic: Dynamic }\n// or use plain serde\n#[derive(Serialize, Deserialize)]\nstruct Foo { a: i32 }","handlingStrategy":"type-guard","validationCode":"// compile-time: only derive BamlSerde on enums marked as unions\n// struct Foo { a: i32, #[serde(flatten)] dynamic: Dynamic }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Read the derive docs: structs need a flattened dynamic field","Keep BamlSerde only on BAML union types","Run cargo check early when adding the derive"],"tags":["rust","derive-macro","serde","compile-time"],"backgroundTag":"unsupported-operation","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}