swc-project/swc · error · TypeError

An element descriptor's .kind property must be either "metho

Error message

An element descriptor's .kind property must be either "method" or "field", but a decorator created an element descriptor with .kind "${kind}"

What it means

The #[derive(Decode)] macro from the ast_node crate folds over the enum's variants to determine the overall EnumType (Unit/One/Struct). With zero variants the fold never produces a value, so enum_type.expect("enum cannot be empty") panics during compilation. This is a proc-macro panic: the compiler aborts with 'proc-macro panicked' and this message, pointing at the derive.

Source

Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_decorate.rs:196

    if (element.kind === "field") obj.initializer = element.initializer;

    return obj;
}
function _toElementDescriptors(elementObjects) {
    if (elementObjects === undefined) return;

    return _to_array(elementObjects).map(function(elementObject) {
        var element = _toElementDescriptor(elementObject);
        _disallowProperty(elementObject, "finisher", "An element descriptor");
        _disallowProperty(elementObject, "extras", "An element descriptor");

        return element;
    });
}
function _toElementDescriptor(elementObject) {
    var kind = String(elementObject.kind);
    if (kind !== "method" && kind !== "field") {
        throw new TypeError("An element descriptor's .kind property must be either \"method\" or" + " \"field\", but a decorator created an element descriptor with" + " .kind \"" + kind + "\"");
    }
    var key = _to_property_key(elementObject.key);
    var placement = String(elementObject.placement);
    if (placement !== "static" && placement !== "prototype" && placement !== "own") {
        throw new TypeError(
            "An element descriptor's .placement property must be one of \"static\","
                + " \"prototype\" or \"own\", but a decorator created an element descriptor"
                + " with .placement \""
                + placement
                + "\""
        );
    }
    var descriptor = elementObject.descriptor;
    _disallowProperty(elementObject, "elements", "An element descriptor");
    var element = { kind: kind, key: key, placement: placement, descriptor: Object.assign({}, descriptor) };
    if (kind !== "field") _disallowProperty(elementObject, "initializer", "A method descriptor");
    else {
        _disallowProperty(descriptor, "get", "The property descriptor of a field descriptor");

View on GitHub (pinned to 5176682b65)

Solutions

  1. Add at least one variant to the enum so the fold can infer the enum type, e.g. a placeholder unit or newtype variant.
  2. If the type is intentionally uninhabited, remove the Decode/Encode derive and hand-implement or gate the type withPhantomData-based never types instead.
  3. Keep the assert message in mind: 'enum cannot be empty' refers to variant count, not to a missing field.

Example fix

// before: empty enum -> proc macro panic 'enum cannot be empty'
#[derive(Decode, Encode)]
enum Phase {}

// after: give it at least one variant
#[derive(Decode, Encode)]
enum Phase {
    Start(u32),
}
Defensive patterns

Strategy: validation

Validate before calling

// There is no runtime API to guard - guard at authoring time.
// Quick check: refuse to derive on empty enums in code review or a lint:
// (clippy) empty enums used only as never-types should not carry AST derives.
// Compile-time canary so an emptied enum fails loudly in tests, not in prod builds:
#[test]
fn ast_enum_derives_compile() {
    #[derive(swc_ast_node::Decode, swc_ast_node::Encode)]
    enum Sample {
        A(u8),
    }
}

Prevention

When it happens

Trigger: Applying #[derive(Decode)] (or the encoding derives) from swc's ast_node crate to an enum with no variants, e.g. `#[derive(Decode)] enum Never {}`. The mirror-image code in encode.rs fails identically for #[derive(Encode)].

Common situations: Writing `enum State {}` as a placeholder for a future state machine; refactoring that temporarily empties an enum while the derive stays attached; codegen that emits enums driven by external schemas which can produce zero cases.

Related errors


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