BoundaryML/baml · error · syn::Error
BamlSerde cannot be derived for enums, use…
Error message
BamlSerde cannot be derived for enums, use `#[serde(untagged)]` on dynamic instead.
What it means
Compile-time error from the `BamlSerde` derive macro: plain enums (without the `union` container attribute) are not supported. BAML union enums must be declared as untagged unions via `#[serde(untagged)]` (plus the union container attr) so the derive emits union serde logic. Emitted by `derive_serde` when input is `Data::Enum` without `container_attrs.union`.
Solutions
- Mark the enum as a union: add `#[serde(untagged)]` and the BAML union container attribute so it routes to `derive_serde_union`
- Use plain `serde` derives if the enum is not a BAML union
- Restructure as a struct with a flattened dynamic field if the data is not a union
Example fix
// before
#[derive(BamlSerde)]
enum Shape { Circle, Square }
// after
#[serde(untagged)]
#[derive(BamlSerde)]
#[baml(union = true)]
enum Shape { Circle(f64), Square { side: f64 } } Defensive patterns
Strategy: type-guard
Validate before calling
// compile-time: ensure enums carry #[serde(untagged)] and the union container attr
Prevention
- Always mark BAML union enums as untagged
- Verify container attribute is present before deriving BamlSerde
- Run cargo check in CI to catch derive misuse
When it happens
Trigger: Applying `#[derive(BamlSerde)]` to an enum lacking the union container attribute, e.g. `#[derive(BamlSerde)] enum E { A, B }` with no `#[serde(untagged)]`/union attr.
Common situations: Deriving BamlSerde on regular tagged enums; forgetting to mark the enum as a union when porting from serde-style enums.
Related errors
- BamlSerde cannot be derived for structs, use…
- Rust unions are not supported for this derive macro.
- capture loss omitted kind
- capture loss omitted reason
- Could not unify Enum
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/248ebc441160ad6e.
Report an issue: GitHub.
Appendix: source
Thrown at languages/rust/baml-macros/src/baml_serde.rs:18
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{Data, DataEnum, DeriveInput, Ident, Result};
use crate::shared::{ContainerAttrs, VariantAttrs};
pub(crate) fn derive_serde(input: &DeriveInput) -> Result<TokenStream> {
let container_attrs = ContainerAttrs::from_attrs(&input.attrs)?;
match &input.data {
Data::Struct(..) => Err(syn::Error::new(
Span::call_site(),
"BamlSerde cannot be derived for structs, use `#[serde(flatten)]` on dynamic instead.",
)),
Data::Enum(data_enum) if container_attrs.union => {
derive_serde_union(data_enum, &input.ident)
}
Data::Enum(..) => Err(syn::Error::new(
Span::call_site(),
"BamlSerde cannot be derived for enums, use `#[serde(untagged)]` on dynamic instead.",
)),
Data::Union(..) => Err(syn::Error::new(
Span::call_site(),
"Rust unions are not supported for this derive macro.",
)),
}
}
fn derive_serde_union(data: &DataEnum, ident: &Ident) -> Result<TokenStream> {
let name = ident.to_string();
let mut literal_serde = Vec::new();
for variant in &data.variants {
let variant_attrs = VariantAttrs::from_attrs(&variant.attrs)?;
let variant_ident = &variant.ident;View on GitHub (pinned to bd85ce9dee)