{"record":{"id":"47c05416579d69f4","repo":"denoland/deno","slug":"unit-structs-cannot-be-destructured","errorCode":null,"errorMessage":"Unit structs cannot be destructured","messagePattern":"Unit structs cannot be destructured","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"libs/ops/conversion/to_v8/mod.rs","lineNumber":74,"sourceCode":"        {\n          #(#fields),*\n        }\n      })\n    }\n    Fields::Unnamed(unnamed) => {\n      let fields = unnamed.unnamed.iter().enumerate().map(|(i, field)| {\n        let idx = syn::Index::from(i);\n        let ident = format_ident!(\"__{i}\", span = field.span());\n        quote!(#idx: #ident)\n      });\n\n      Ok(quote! {\n        {\n          #(#fields),*\n        }\n      })\n    }\n    Fields::Unit => Err(Error::new(\n      fields.span(),\n      \"Unit structs cannot be destructured\",\n    )),\n  }\n}\n\nfn convert_or_serde<T: quote::ToTokens>(\n  serde: bool,\n  span: proc_macro2::Span,\n  value: T,\n) -> TokenStream {\n  if serde {\n    quote_spanned! { span =>\n      ::deno_core::serde_v8::to_v8(\n        __scope,\n        #value,\n      ).map_err(::deno_error::JsErrorBox::from_err)?\n    }","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/libs/ops/conversion/to_v8/mod.rs#L56-L92","documentation":"ToV8 codegen destructures the value with 'let Self #fields = self;' so each field can be converted; destruct_fields handles named and unnamed fields but has no pattern for Fields::Unit, so a unit struct (struct Foo;) fails with this compile error at the fields' span. The derive cannot destructure what has no fields to bind.","triggerScenarios":"Deriving ToV8 on a unit struct: #[derive(ToV8)] struct Unit; used as an op return type or nested value.","commonSituations":"Marker types (state machines' PhantomData-like units) caught by blanket derives; stripping a struct's fields during a refactor while leaving #[derive(ToV8)] on it.","solutions":["Remove the ToV8 derive from the unit type — it carries no data to convert.","Give it a field or make it a newtype (struct Unit(())) so destruction has something to bind.","Hand-write a ToV8 impl returning v8::undefined if the type must appear in an op signature."],"exampleFix":"// before\n#[derive(ToV8)]\nstruct Unit; // error: Unit structs cannot be destructured\n\n// after\n// drop the derive, or carry data:\n#[derive(ToV8)]\nstruct Unit(u32);","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Don't derive ToV8 on unit structs; they carry nothing to serialize.","If a type must appear in a signature, give it at least one field or hand-write the impl returning undefined."],"tags":["proc-macro","derive","to-v8","unit-struct","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-14T00:17:10.932Z"}