neon-bindings/neon · error

class must be implemented for a type name

Error message

class must be implemented for a type name

What it means

The `#[neon::class]` (class_with_name) attribute macro only supports being applied to a struct/enum type definition whose name is the class type. When the macro expands it inspects the last path segment of the annotated item to derive the class name; if the item is anything other than a simple type name (e.g. a function, tuple struct with anonymous fields, impl block, or complex path) the macro panics with this message instead of compiling gracefully.

Solutions

  1. Move `#[neon::class]` so it sits directly on a named struct (or enum) definition.
  2. Ensure the type is a unit/named struct with an explicit identifier, e.g. `struct Greeter { ... }`, not a tuple or unit struct.
  3. If wrapping an imported type, define a new named wrapper struct in your crate and annotate that instead.
  4. Remove the macro from any fn/impl/mod items it was accidentally attached to.

Example fix

// before
#[neon::class]
fn make_greeter() -> Greeter { Greeter }

// after
#[neon::class]
struct Greeter { /* fields */ }
Defensive patterns

Strategy: validation

Validate before calling

// attach the macro only to named structs/enum types
#[neon::class]
struct Greeter { /* named fields */ }
// sanity check in review/CI: grep for #[neon::class] lines and confirm
// the next non-attribute line starts with `struct` or `enum`

Prevention

When it happens

Trigger: Applying `#[neon::class]` to a non-type item (a fn, mod, impl, or trait); applying it to a unit/tuple struct where no nameable ident can be extracted; using the macro on a re-exported or path-qualified type instead of a locally defined named struct.

Common situations: Copy-pasting the attribute onto the wrong item; trying to register an existing imported type (only locally defined types work); refactoring a named struct into a tuple struct and forgetting to move the attribute; applying macros in bulk across a module.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of neon-bindings/neon@38960e4381 (2026-09-13). Data as JSON: /api/errors/45a6261fe988dbf3. Report an issue: GitHub.

Appendix: source

Thrown at crates/neon-macros/src/class/mod.rs:847

    _attr: proc_macro::TokenStream,
    item: proc_macro::TokenStream,
    custom_class_name: Option<String>,
) -> proc_macro::TokenStream {
    let mut impl_block = syn::parse_macro_input!(item as syn::ItemImpl);

    // Parse the item as an implementation block
    let syn::ItemImpl { self_ty, items, .. } = impl_block.clone();

    let class_ident = match *self_ty {
        syn::Type::Path(syn::TypePath {
            path: syn::Path { segments, .. },
            ..
        }) => {
            let syn::PathSegment { ident, .. } = segments.last().unwrap();
            ident.clone()
        }
        _ => {
            panic!("class must be implemented for a type name");
        }
    };
    let class_name = custom_class_name.unwrap_or_else(|| class_ident.to_string());

    // Group the items into `const` and `fn` categories
    let ClassItems {
        consts,
        fns,
        constructor,
        has_finalizer,
    } = match group_class_items(items.clone()) {
        Ok(items) => items,
        Err(err) => {
            // If sorting fails, return the error as a compile error
            return err.to_compile_error().into();
        }
    };

View on GitHub (pinned to 38960e4381)