tauri-apps/tauri · error · syn::Error

expected "camelCase" or "snake_case"

Error message

expected "camelCase" or "snake_case"

What it means

rename_all on #[tauri::command] controls how Rust argument names are exposed to the frontend, and supports exactly two values: "camelCase" (default) and "snake_case". The parser matches the string literal against those exact spellings and rejects anything else, with the error span on the string literal itself so it points at the bad value.

Source

Thrown at crates/tauri-macros/src/command/wrapper.rs:72

    let attrs = Punctuated::<WrapperAttributeKind, Token![,]>::parse_terminated(input)?;
    for attr in attrs {
      match attr {
        WrapperAttributeKind::Meta(Meta::List(_)) => {
          return Err(syn::Error::new(input.span(), "unexpected list input"));
        }
        WrapperAttributeKind::Meta(Meta::NameValue(v)) => {
          if v.path.is_ident("rename_all") {
            if let Expr::Lit(ExprLit {
              lit: Lit::Str(s),
              attrs: _,
            }) = v.value
            {
              wrapper_attributes.argument_case = match s.value().as_str() {
                "snake_case" => ArgumentCase::Snake,
                "camelCase" => ArgumentCase::Camel,
                _ => {
                  return Err(syn::Error::new(
                    s.span(),
                    "expected \"camelCase\" or \"snake_case\"",
                  ))
                }
              };
            }
          } else if v.path.is_ident("rename") {
            if let Expr::Lit(ExprLit {
              lit: Lit::Str(s), ..
            }) = v.value
            {
              let lit = s.value();
              wrapper_attributes.rename = RenamePolicy::Rename(quote!(#lit));
            } else {
              return Err(syn::Error::new(
                v.span(),
                "expected string literal for rename",
              ));

View on GitHub (pinned to 52e4b6e71d)

Solutions

  1. Use exactly #[tauri::command(rename_all = "snake_case")] or "camelCase"
  2. If you need another casing on the JS side, wrap/rename the arguments in the frontend call instead
  3. Check the tauri command docs for your pinned version for the current accepted set

Example fix

// before
#[tauri::command(rename_all = "PascalCase")]
fn get_user(user_id: u32) {}
// after
#[tauri::command(rename_all = "camelCase")]
fn get_user(user_id: u32) {} // JS calls invoke('get_user', { userId: 32 })
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: #[tauri::command(rename_all = "PascalCase")], "snakeCase", "SCREAMING_SNAKE_CASE", "kebab-case", or any casing variant that is not byte-for-byte camelCase or snake_case.

Common situations: Porting serde rename_all vocabulary (which supports many more cases) to tauri commands; capitalization typos like "Snake_Case"; assuming the frontend framework's naming convention is accepted.

Related errors


AI-assisted analysis of tauri-apps/tauri@52e4b6e71d (2026-08-20). Data as JSON: /api/errors/d7f01dc2e8199470. Report an issue: GitHub.