leptos-rs/leptos · error

cannot use receiver types in server function macro

Error message

cannot use receiver types in server function macro

What it means

The #[server] macro only supports free functions (and generates a struct for them). If the annotated item is a method — i.e. its signature has a self receiver — codegen cannot produce a standalone server function struct, so the macro errors with this message.

Source

Thrown at server_fn_macro/src/lib.rs:1270

                    builtin_encoding = true;
                }
                "cbor" => {
                    input = Some(type_from_ident(syn::parse_quote!(Cbor)));
                    output = Some(type_from_ident(syn::parse_quote!(Cbor)));
                    builtin_encoding = true;
                }
                "getcbor" => {
                    input = Some(type_from_ident(syn::parse_quote!(GetUrl)));
                    output = Some(type_from_ident(syn::parse_quote!(Cbor)));
                    builtin_encoding = true;
                }
                "getjson" => {
                    input = Some(type_from_ident(syn::parse_quote!(GetUrl)));
                    output = Some(syn::parse_quote!(Json));
                    builtin_encoding = true;
                }
                _ => {
                    return Err(syn::Error::new(
                        encoding.span(),
                        "Encoding not found.",
                    ))
                }
            }
        }

        Ok(Self {
            struct_name,
            prefix,
            input,
            input_derive,
            output,
            fn_path,
            builtin_encoding,
            server,
            client,
            custom_wrapper,

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Move the function out of the impl block and make it a free async function.
  2. Replace the `self` receiver with explicit parameters (e.g. pass the needed fields as arguments).
  3. Use #[server] only on associated-style free functions, calling the method internally if needed.

Example fix

// before
impl Api {
    #[server]
    async fn load(&self, id: u32) -> Result<Item, ServerFnError> { self.fetch(id).await }
}
// after
#[server]
async fn load(api: &Api, id: u32) -> Result<Item, ServerFnError> { api.fetch(id).await }
Defensive patterns

Strategy: validation

Validate before calling

// Guard: never place #[server] on an impl method.
// Verify before compiling by checking signatures lack a self receiver.
fn assert_no_receiver(sig: &str) { assert!(!sig.contains("&self") && !sig.contains("&mut self") && !sig.contains("self:"), "#[server] cannot be used on methods"); }

Prevention

When it happens

Trigger: Annotating an impl-block method like `impl Api { #[server] async fn load(&self) ... }`; keeping a `&self`/`&mut self`/`self` parameter after adding #[server]; moving an existing method behind the macro during a refactor.

Common situations: Developers trying to expose existing service/trait methods as server functions instead of extracting them into free functions.

Related errors


AI-assisted analysis of leptos-rs/leptos@32d20f6c9d (2026-09-01). Data as JSON: /api/errors/ec43eceb4d7ddb01. Report an issue: GitHub.