neon-bindings/neon · error
Expected 'class' in export attribute
Error message
Expected 'class' in export attribute
What it means
The Meta parser for the #[neon] export attribute expects the literal identifier `class` as the first token of the attribute. Any other identifier (e.g. `module`, `fn`, or a typo like `clas`) is rejected with this error at the token's span.
Solutions
- Use exactly `#[neon(class)]` for class exports
- Check the neon version's documented attribute syntax and correct the token spelling
- Remove the attribute entirely if a different neon entry point (e.g. main) was intended
Example fix
// before
#[neon(modlue)]
impl Greet { ... }
// after
#[neon(class)]
impl Greet { ... } Defensive patterns
Strategy: validation
Validate before calling
// verify the attribute token before applying
const EXPECTED_ATTR: &str = "class";
fn check_attr(attr: &str) -> bool { attr.trim() == EXPECTED_ATTR } Prevention
- Use the exact documented attribute `#[neon(class)]`
- Double-check attribute spelling when copying examples
- Consult the neon docs for the correct entry-point attributes per version
When it happens
Trigger: Writing an attribute other than `class` after #[neon], e.g. `#[neon(module)]` where only class export meta is parsed, or misspelling `class`.
Common situations: Copy-pasted attribute syntax from other macro systems; confusion between #[neon::main], #[neon(class)], and module exports; typos like `#[neon(cls)]`.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Expected an owned `Channel` instead of a context reference.
- Context is not available in async functions. Try a…
- Expected a context argument after `&self` when using…
- Unexpected second receiver argument.
- Cannot combine `async fn` with `#[neon(async)]` attribute
AI-assisted analysis of neon-bindings/neon@38960e4381 (2026-09-13).
Data as JSON: /api/errors/070938eca925d204.
Report an issue: GitHub.
Appendix: source
Thrown at crates/neon-macros/src/export/class/meta.rs:17
use syn::parse::{Parse, ParseStream};
/// Metadata for class exports
#[derive(Default)]
pub(crate) struct Meta {
/// Name for the JavaScript class itself (used in class definition)
pub class_name: Option<String>,
/// Name for the module export binding
pub export_name: Option<String>,
}
impl Parse for Meta {
fn parse(input: ParseStream) -> syn::Result<Self> {
// Parse "class" token
let class_token: syn::Ident = input.parse()?;
if class_token != "class" {
return Err(syn::Error::new(
class_token.span(),
"Expected 'class' in export attribute",
));
}
let mut meta = Meta::default();
// Check for parenthesized attributes: class(name = "...")
if input.peek(syn::token::Paren) {
let content;
syn::parenthesized!(content in input);
// Parse attributes inside parentheses
while !content.is_empty() {
let name_token: syn::Ident = content.parse()?;
match name_token.to_string().as_str() {
"name" => {View on GitHub (pinned to 38960e4381)