swc-project/swc · error

unknown member must be a tag and a value

Error message

unknown member must be a tag and a value

What it means

The #[encoding(unknown)] variant is how the generated encoder round-trips unknown CBOR tags. The macro's match on its field count only handles 1 (encode the bare tag) and 2 (encode cbor4ii Tag(tag, value)); any other arity has no meaning, so expansion panics with 'unknown member must be a tag and a value'. #[ast_node] generates the correct shape automatically; this fires for hand-written Encode derives.

Source

Thrown at crates/ast_node/src/encoding/encode.rs:109

                    );

                    match &unknown.fields {
                        syn::Fields::Unnamed(fields) => match fields.unnamed.len() {
                            1 => {
                                assert_eq!(enum_type, EnumType::Unit);
                                syn::parse_quote! {
                                    #ident::#name(tag)
                                        => tag.encode(writer)?,
                                }
                            }
                            2 => {
                                assert_eq!(enum_type, EnumType::One);
                                syn::parse_quote! {
                                    #ident::#name(tag, value)
                                        => cbor4ii::core::types::Tag((*tag).into(), &*value).encode(writer)?,
                                }
                            }
                            _ => panic!("unknown member must be a tag and a value"),
                        },
                        _ => panic!("named enum unsupported"),
                    }
                });

            if matches!(enum_type, EnumType::Struct) {
                assert!(
                    unknown_arm.is_none(),
                    "struct enum does not allow unknown variants"
                );
            }

            let mut discriminant: u32 = 0;
            let fields = iter.map(|field| -> syn::Arm {
                match field.discriminant.as_ref() {
                    Some((_, syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(lit), .. }))) => {
                        discriminant = lit.base10_parse::<u32>().unwrap();
                    },

View on GitHub (pinned to 5176682b65)

Solutions

  1. Declare it as exactly `#[encoding(unknown)] Unknown(u32)` or `#[encoding(unknown)] Unknown(u32, YourUnknownType)`.
  2. Prefer #[ast_node(...)] so the Unknown variant is generated correctly.
  3. Keep the unknown variant first — the macro also asserts it precedes tagged variants.

Example fix

// before
#[derive(Encode, Decode)]
enum Expr {
    #[encoding(unknown)]
    Unknown(u32, u32, u32),
    Num { value: f64 },
}

// after — tag + value tuple
#[derive(Encode, Decode)]
enum Expr {
    #[encoding(unknown)]
    Unknown(u32, swc_common::unknown::Unknown),
    Num { value: f64 },
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Hand-writing derive(Encode) (not via #[ast_node]) on an enum with a #[encoding(unknown)] variant of arity 0 or 3+ unnamed fields.

Common situations: Custom AST nodes targeting swc_ast_unknown builds; manually porting the generated Unknown variant with the wrong shape.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/63c10c3e3390c363. Report an issue: GitHub.