{"record":{"id":"a05a3bec2b7a3332","repo":"yewstack/yew","slug":"missing-type-input","errorCode":null,"errorMessage":"missing `type Input`","messagePattern":"missing `type Input`","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"packages/yew-link-macro/src/lib.rs","lineNumber":82,"sourceCode":"\n    for item in &impl_block.items {\n        match item {\n            ImplItem::Type(t) if t.ident == \"Input\" => input_ty = Some(&t.ty),\n            ImplItem::Type(t) if t.ident == \"Context\" => context_ty = Some(&t.ty),\n            ImplItem::Type(t) if t.ident == \"Error\" => error_ty = Some(&t.ty),\n            ImplItem::Fn(f) if f.sig.ident == \"resolve\" => resolve_fn = Some(f),\n            other => {\n                return Err(syn::Error::new_spanned(\n                    other,\n                    \"#[linked_state] expects only `type Input`, `type Context`, `type Error` \\\n                     (optional), and `async fn resolve`\",\n                ));\n            }\n        }\n    }\n\n    let input_ty =\n        input_ty.ok_or_else(|| syn::Error::new(Span::call_site(), \"missing `type Input`\"))?;\n    let context_ty =\n        context_ty.ok_or_else(|| syn::Error::new(Span::call_site(), \"missing `type Context`\"))?;\n    let resolve_fn = resolve_fn\n        .ok_or_else(|| syn::Error::new(Span::call_site(), \"missing `async fn resolve`\"))?;\n\n    if resolve_fn.sig.asyncness.is_none() {\n        return Err(syn::Error::new_spanned(\n            resolve_fn.sig.fn_token,\n            \"`resolve` must be an async fn\",\n        ));\n    }\n\n    let params: Vec<_> = resolve_fn.sig.inputs.iter().collect();\n    if params.len() != 2 {\n        return Err(syn::Error::new_spanned(\n            &resolve_fn.sig.inputs,\n            \"`resolve` must take exactly two parameters: context and input references\",\n        ));","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/packages/yew-link-macro/src/lib.rs#L64-L100","documentation":"`#[linked_state]` (packages/yew-link-macro) rewrites an `impl LinkedState for T` block into the framework's `LinkedState`/`LinkedStateResolve` impls. It walks the impl items collecting `type Input`, `type Context`, optional `type Error`, and `async fn resolve`; after the walk (lib.rs:81-82), a missing `type Input` produces this `syn::Error` at the macro call site. `Input` is the argument type the server-side `resolve` receives, so the macro cannot generate code without it.","triggerScenarios":"An impl block annotated with `#[linked_state]` that declares `type Context` and `async fn resolve` but contains no `type Input = …;` item. (Writing a differently named associated type instead hits the 'expects only …' error earlier, so this message means `Input` is simply absent.)","commonSituations":"First use of the linked-state API where the boilerplate `type Input` line was trimmed from the example, or refactoring the impl and deleting what looked like an unused associated type.","solutions":["Add `type Input = u32;` (or your id type) to the impl block, matching what `resolve`'s second parameter accepts","Copy the full skeleton from the macro's doc comment: `type Context`, `type Input`, then `async fn resolve(&Ctx, &Input) -> Self`","Keep only the four allowed items — any other item is rejected with its own error"],"exampleFix":"// before\n#[linked_state]\nimpl LinkedState for Post {\n    type Context = DbPool;\n\n    async fn resolve(ctx: &DbPool, id: &u32) -> Self {\n        ctx.get_post(*id).await\n    }\n}\n\n// after\n#[linked_state]\nimpl LinkedState for Post {\n    type Context = DbPool;\n    type Input = u32;\n\n    async fn resolve(ctx: &DbPool, id: &u32) -> Self {\n        ctx.get_post(*id).await\n    }\n}","handlingStrategy":"validation","validationCode":"// Pre-flight: the impl block must contain `type Input` before adding the attribute\n// fn has_input_item(imp: &syn::ItemImpl) -> bool {\n//     imp.items.iter().any(|i| matches!(i, syn::ImplItem::Type(t) if t.ident == \"Input\"))\n// }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start every `#[linked_state]` impl from the documented skeleton: `type Context`, `type Input`, optional `type Error`, `async fn resolve` — nothing else","Keep `type Input` aligned with the second parameter type of `resolve` so the macro's later arity/type checks pass too","Run `cargo check` on the package immediately after adding the attribute; all missing-item errors point at the macro invocation"],"tags":["rust","yew","linked-state","proc-macro","associated-type"],"backgroundTag":"proc-macro-missing-required-item","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}