{"record":{"id":"d065df6ed2c80a44","repo":"denoland/deno","slug":"fromv8-enum-derive-currently-supports-only-unit-an","errorCode":null,"errorMessage":"FromV8 enum derive currently supports only unit and single-element newtype variants","messagePattern":"FromV8 enum derive currently supports only unit and single-element newtype variants","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"libs/ops/conversion/from_v8/enum.rs","lineNumber":82,"sourceCode":"          }\n        };\n        let key = crate::get_internalized_string(Ident::new(\n          &tag_name,\n          variant_ident.span(),\n        ))?;\n        variant_arms.push(quote! {\n          {\n            let __key = #key;\n            if let Some(__inner) = __obj.get(__scope, __key)\n              && !__inner.is_undefined()\n            {\n              return Ok(Self::#variant_ident(#converter));\n            }\n          }\n        });\n      }\n      _ => {\n        return Err(Error::new(\n          variant_span,\n          \"FromV8 enum derive currently supports only unit and single-element newtype variants\",\n        ));\n      }\n    }\n  }\n\n  let unit_branch = if unit_arms.is_empty() {\n    quote! {}\n  } else {\n    quote! {\n      if let Ok(__s) =\n        ::deno_core::v8::Local::<::deno_core::v8::String>::try_from(__value)\n      {\n        let __s = __s.to_rust_string_lossy(__scope);\n        match __s.as_str() {\n          #(#unit_arms)*\n          _ => {","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/libs/ops/conversion/from_v8/enum.rs#L64-L100","documentation":"#[derive(FromV8)] on an enum currently implements only the externally-tagged shape: unit variants (matched by their camelCased tag string) and single-element newtype variants (matched when the key exists and is not undefined). Any struct variant (V { a: u32 }) or tuple variant with zero or 2+ fields falls into the catch-all arm and produces this compile-time error on the offending variant's span.","triggerScenarios":"Deriving FromV8 on an enum that contains a struct variant like Point { x: f64, y: f64 } or a multi-field tuple variant like Pair(u32, u32); also a variant declared with empty parens V().","commonSituations":"Porting serde-tagged enums into deno_core ops and expecting the same flexibility; adding a data-carrying variant to a previously unit-only op enum; mixing #[to_v8] (which does support struct variants) with #[from_v8] and assuming symmetric support.","solutions":["Convert each struct/multi-field variant into a newtype variant wrapping a struct: move the fields into their own #[derive(FromV8)] struct and declare the variant as Point(Point).","Keep single payloads as one-field newtype variants (V(u32)) — those and unit variants are the only supported shapes.","For complex payloads, use the serde path on the newtype variant so serde_v8::from_v8 handles the inner value instead of the derive."],"exampleFix":"// before\n#[derive(FromV8)]\nenum Shape {\n  Circle,\n  Point { x: f64, y: f64 }, // error: only unit and single-element newtype variants\n}\n\n// after\n#[derive(FromV8)]\nstruct Point {\n  x: f64,\n  y: f64,\n}\n\n#[derive(FromV8)]\nenum Shape {\n  Circle,\n  Point(Point), // newtype variant wrapping a derived struct\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":"// design-time shape check: FromV8-compatible enum variants are unit or single-newtype only\n// variant is OK:   Unit            | Newtype(OneType)\n// variant is NOT:  Struct { a: A } | Tuple(A, B) | Empty()\n// when reviewing an enum before adding #[derive(FromV8)]:\n//   every variant must match `Ident` or `Ident(Ty)` with exactly one Ty","tryCatchPattern":null,"preventionTips":["Keep op-facing FromV8 enums to unit + single-newtype variants; model richer payloads as separate derived structs wrapped in newtype variants.","Mirror the supported shapes in a test file that derives FromV8, so CI catches unsupported variants the moment they are added.","Remember ToV8 is more permissive than FromV8 — never assume an enum that serializes can also be deserialized by these derives."],"tags":["proc-macro","derive","from-v8","enum","compile-time","deno-core"],"backgroundTag":"derive-macro-unsupported-shape","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}