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

  1. Use exactly `#[neon(class)]` for class exports
  2. Check the neon version's documented attribute syntax and correct the token spelling
  3. 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

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


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)