{"record":{"id":"d5329e59d03e2044","repo":"tauri-apps/tauri","slug":"only-named-wildcard-struct-and-tuple-struct-arg","errorCode":null,"errorMessage":"only named, wildcard, struct, and tuple struct arguments allowed","messagePattern":"only named, wildcard, struct, and tuple struct arguments allowed","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"crates/tauri-macros/src/command/wrapper.rs","lineNumber":484,"sourceCode":"  // we have no use for self arguments\n  let mut arg = match arg {\n    FnArg::Typed(arg) => arg.pat.as_ref().clone(),\n    FnArg::Receiver(arg) => {\n      return Err(syn::Error::new(\n        arg.span(),\n        \"unable to use self as a command function parameter\",\n      ))\n    }\n  };\n\n  // we only support patterns that allow us to extract some sort of keyed identifier\n  let mut key = match &mut arg {\n    Pat::Ident(arg) => arg.ident.unraw().to_string(),\n    Pat::Wild(_) => \"\".into(), // we always convert to camelCase, so \"_\" will end up empty anyways\n    Pat::Struct(s) => super::path_to_command(&mut s.path).ident.to_string(),\n    Pat::TupleStruct(s) => super::path_to_command(&mut s.path).ident.to_string(),\n    err => {\n      return Err(syn::Error::new(\n        err.span(),\n        \"only named, wildcard, struct, and tuple struct arguments allowed\",\n      ))\n    }\n  };\n\n  // also catch self arguments that use FnArg::Typed syntax\n  if key == \"self\" {\n    return Err(syn::Error::new(\n      key.span(),\n      \"unable to use self as a command function parameter\",\n    ));\n  }\n\n  match attributes.argument_case {\n    ArgumentCase::Camel => {\n      key = key.to_lower_camel_case();\n    }","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/tauri-apps/tauri/blob/52e4b6e71d8632a7e648f866c442e287ecddee34/crates/tauri-macros/src/command/wrapper.rs#L466-L502","documentation":"The command macro derives each argument's frontend key from the parameter pattern, so only patterns that yield an identifier work: plain identifiers, the wildcard _, struct patterns, and tuple-struct patterns. Everything else — tuple destructuring, references, literals — has no stable key and is rejected with 'only named, wildcard, struct, and tuple struct arguments allowed'.","triggerScenarios":"#[tauri::command] fn resize((w, h): (u32, u32)) (Pat::Tuple), fn print(&name: &String) (Pat::Ref), or any destructuring pattern the key-extraction match cannot handle.","commonSituations":"Writing idiomatic Rust destructuring in command signatures; porting handlers that took tuples; ref parameters borrowed for convenience.","solutions":["Take the tuple/reference as a single named parameter and destructure in the body","Use tauri's automatic deserialization: a struct parameter gives you named keys on the JS side","Keep patterns to plain idents or _ in command signatures"],"exampleFix":"// before\n#[tauri::command]\nfn resize((w, h): (u32, u32)) { /* ... */ }\n// after\n#[tauri::command]\nfn resize(size: (u32, u32)) {\n  let (w, h) = size;\n  // JS: invoke('resize', { size: [800, 600] })\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use plain identifier (or _) parameter patterns in command signatures","Destructure tuples and references inside the function body","Model grouped arguments as a struct parameter — tauri deserializes it as named keys"],"tags":["macros","command","patterns","compile-time","arguments"],"backgroundTag":"unsupported-macro-input","analyzedSha":"52e4b6e71d8632a7e648f866c442e287ecddee34","analyzedAt":"2026-08-20T13:59:20.734Z","contentChangedAt":"2026-08-20T13:59:20.734Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}