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

  1. Remove #[to_v8(serde)] from the unit variant — unit variants are already serialized correctly as their (optionally renamed) tag string.
  2. If the variant must carry serde-encoded data, change it into a newtype variant (e.g. None(Option<u32>)) and keep serde on that.
  3. 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

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


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/dcf4e2d58b4f6fa2. Report an issue: GitHub.