neon-bindings/neon · error

Class methods must have a `self` receiver (`&self` or `&mut…

Error message

Class methods must have a `self` receiver (`&self` or `&mut self`) as their first parameter

What it means

Every non-constructor method in a neon class must take the instance as its first parameter via a `self` receiver (`&self`, `&mut self`, or `self`). The macro needs the receiver to access and expose the underlying Rust object from JavaScript; a method without one has no instance to operate on.

Solutions

  1. Add a receiver as the first parameter, typically `&self` (or `&mut self` for mutation).
  2. If the function doesn't need the instance, move it outside the impl block or mark it as a standalone function rather than a class method.
  3. If a JS static method is intended, note that neon class methods are instance-bound; restructure accordingly.

Example fix

// before
#[neon]
impl Counter {
    fn get() -> JsResult<JsNumber> { ... }
}

// after
#[neon]
impl Counter {
    fn get(&self) -> JsResult<JsNumber> { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

// All exposed class methods need a receiver
fn assert_class_method(fn_name: &str, params: &[&str]) -> Result<(), String> {
    if fn_name != "new" && !params.first().map(|p| p.ends_with("self")).unwrap_or(false) {
        return Err("class methods must take self as first parameter".into());
    }
    Ok(())
}

Prevention

When it happens

Trigger: Declaring any regular class method like `fn get(&self)`... actually `fn get()` / `fn set(value: f64)` with no `self` parameter in a `#[neon] impl` block (constructors named `new` are exempt).

Common situations: Writing static-style helper functions inside the impl block and exposing them as methods; accidentally deleting the receiver during refactoring; translating JS static methods into neon class methods without realizing all class methods are instance methods.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

    if sig.ident == "new" {
        if let Some(syn::FnArg::Receiver(_)) = sig.inputs.first() {
            return Err(syn::Error::new(
                sig.ident.span(),
                "Constructor methods cannot have a `self` receiver",
            ));
        }
    } else {
        fn starts_with_self_arg(sig: &syn::Signature) -> bool {
            if let Some(first_arg) = sig.inputs.first() {
                matches!(first_arg, syn::FnArg::Receiver(_))
            } else {
                false
            }
        }

        // Check for self parameter in non-constructor methods
        if !starts_with_self_arg(sig) {
            return Err(syn::Error::new(
                sig.ident.span(),
                "Class methods must have a `self` receiver (`&self` or `&mut self`) as their first parameter",
            ));
        }
    }

    Ok(())
}

// Check if a method has a `this` parameter (adapted from export function)
// For methods: &self is 1st, context is 2nd (optional), this is 3rd (or 2nd if no context)
fn check_this(opts: &meta::Meta, sig: &syn::Signature, has_context: bool) -> bool {
    static THIS: &str = "this";

    // Forced `this` argument
    if opts.this {
        return true;
    }

View on GitHub (pinned to 38960e4381)