leptos-rs/leptos · error

expected string literal

Error message

expected string literal

What it means

In the #[server] macro's argument list, only the FIRST positional argument is allowed (the struct name, and it must be an Ident). If a second bare (non-keyword) identifier argument appears, the parser rejects it with 'expected string literal' because positional slot 2+ only accepts string literals (prefix, encoding, endpoint).

Source

Thrown at server_fn_macro/src/lib.rs:1201

                                "keyword argument repeated: `impl_deref`",
                            ));
                        }
                        impl_deref = Some(stream.parse()?);
                    } else if key == "protocol" {
                        if protocol.is_some() {
                            return Err(syn::Error::new(
                                key.span(),
                                "keyword argument repeated: `protocol`",
                            ));
                        }
                        protocol = Some(stream.parse()?);
                    } else {
                        return Err(lookahead.error());
                    }
                } else {
                    let value = key_or_value;
                    if use_key_and_value {
                        return Err(syn::Error::new(
                            value.span(),
                            "positional argument follows keyword argument",
                        ));
                    }
                    if arg_pos == 1 {
                        struct_name = Some(value)
                    } else {
                        return Err(syn::Error::new(
                            value.span(),
                            "expected string literal",
                        ));
                    }
                }
            } else if lookahead.peek(LitStr) {
                if use_key_and_value {
                    return Err(syn::Error::new(
                        stream.span(),
                        "If you use keyword arguments (e.g., `name` = \

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Remove the extra bare identifier — only one positional argument is allowed.
  2. If you meant an option, give it its keyword: e.g. encoding = "Url".
  3. If you meant a string option, pass a string literal such as "api/prefix" instead of an ident.

Example fix

// before
#[server(MyServerFn, UrlEnc)]
// after
#[server(MyServerFn, encoding = "UrlEnc")]
Defensive patterns

Strategy: validation

Validate before calling

// Only the first bare Ident is legal; any other option needs `key = value`.
fn is_positional_ok(args: &[&str]) -> bool {
    args.iter().skip(1).all(|a| a.contains('='))
}
assert!(is_positional_ok(&["MyFn", "UrlEnc"])); // fails before compiling

Prevention

When it happens

Trigger: #[server(MyServerFn, SomeExtraIdent)] — a second bare ident after the function/struct name; forgetting the `= value` after an intended keyword so it is parsed as a positional ident; typos like #[server(MyFn, UrlEnc)] instead of encoding = "UrlEnc".

Common situations: Users migrating between the legacy positional form (name, "prefix", "encoding", "endpoint") and keyword form, mixing bare idents where strings were required.

Related errors


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