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
- Move `#[neon::class]` so it sits directly on a named struct (or enum) definition.
- Ensure the type is a unit/named struct with an explicit identifier, e.g. `struct Greeter { ... }`, not a tuple or unit struct.
- If wrapping an imported type, define a new named wrapper struct in your crate and annotate that instead.
- 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
- Never place #[neon::class] on functions, impls, or modules
- Only annotate locally defined named types, not imports or tuple structs
- Keep macro and its target adjacent; avoid bulk-annotating with macro_rules
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
- The `neon::main` macro must only be used once
- Expected `&mut Cx` instead of a `Channel` reference.
- Context parameters must be a `&mut` reference. Try `&mut…
- Unexpected `Channel` in sync method. Use `&mut…
- Must be a `&mut` reference.
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)