denoland/deno · error · syn::Error
Cannot use serde on unit variant
Error message
Cannot use serde on unit variant
What it means
In #[derive(ToV8)] on enums, #[to_v8(serde)] on a variant delegates that variant's conversion to serde_v8. A unit variant has no field value to hand to serde (it serializes as just its tag name), so the derive rejects serde on Fields::Unit with this compile error instead of generating code that would not compile or would double-encode the tag.
Source
Thrown at libs/ops/conversion/to_v8/enum.rs:219
.unnamed
.into_iter()
.enumerate()
.map(|(i, field)| format_ident!("__{}", i, span = field.span()))
.collect();
let indices: Vec<_> = (0..len as u32).collect();
Ok(quote! {
let __arr = ::deno_core::v8::Array::new(__scope, #len as i32);
#(
let __val = ::deno_core::serde_v8::to_v8(__scope, #field_idents)
.map_err(::deno_error::JsErrorBox::from_err)?;
__arr.set_index(__scope, #indices, __val);
)*
Ok::<_, ::deno_error::JsErrorBox>(__arr.into())
})
}
}
Fields::Unit => Err(Error::new(span, "Cannot use serde on unit variant")),
}
}
#[derive(Default)]
enum EnumMode {
#[default]
ExternallyTagged,
InternallyTagged {
tag: TokenStream,
},
AdjacentlyTagged {
tag: TokenStream,
content: TokenStream,
},
Untagged,
}
impl EnumMode {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Remove #[to_v8(serde)] from the unit variant — unit variants are already serialized correctly as their (optionally renamed) tag string.
- If the variant must carry serde-encoded data, change it into a newtype variant (e.g. None(Option<u32>)) and keep serde on that.
- Use #[to_v8(rename = "...")] if the goal was only to control the emitted tag name.
Example fix
// before
#[derive(ToV8)]
enum Result {
#[to_v8(serde)]
Ok, // error: Cannot use serde on unit variant
Error(String),
}
// after
#[derive(ToV8)]
enum Result {
Ok,
Error(String),
} Defensive patterns
Strategy: validation
Prevention
- Apply #[to_v8(serde)] only to variants that carry data; unit variants already emit their tag name correctly.
- Use #[to_v8(rename = "...")] when the goal is just a different tag string.
When it happens
Trigger: Annotating a unit variant with #[to_v8(serde)], e.g. #[to_v8(serde)] None, inside a #[derive(ToV8)] enum.
Common situations: Applying #[to_v8(serde)] at the variant level to 'keep serialization consistent' across all variants; copy-pasting the attribute from a data-carrying variant to a unit one; IDE auto-completing the attribute onto every variant.
Related errors
- Cannot combine `untagged` with `tag` or `content`
- `content` requires `tag` to be specified
- FromV8 enum derive currently supports only unit and single-e
- Unions are not supported
- Unit structs cannot be destructured
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/dcf4e2d58b4f6fa2.
Report an issue: GitHub.