yewstack/yew · error · syn::Error
missing `async fn resolve`
Error message
missing `async fn resolve`
What it means
`#[linked_state]` scans the impl block for a method named `resolve` (lib.rs:70); if none exists, this error is raised at the macro call site (lib.rs:85-86). `resolve` is the server-side async function whose body is moved into the generated `LinkedStateResolve::resolve`, so without it there is nothing to expand. Note this is the 'entirely absent' case — a `resolve` that exists but lacks `async` produces the separate error '`resolve` must be an async fn' at lib.rs:88-93.
Source
Thrown at packages/yew-link-macro/src/lib.rs:86
ImplItem::Type(t) if t.ident == "Context" => context_ty = Some(&t.ty),
ImplItem::Type(t) if t.ident == "Error" => error_ty = Some(&t.ty),
ImplItem::Fn(f) if f.sig.ident == "resolve" => resolve_fn = Some(f),
other => {
return Err(syn::Error::new_spanned(
other,
"#[linked_state] expects only `type Input`, `type Context`, `type Error` \
(optional), and `async fn resolve`",
));
}
}
}
let input_ty =
input_ty.ok_or_else(|| syn::Error::new(Span::call_site(), "missing `type Input`"))?;
let context_ty =
context_ty.ok_or_else(|| syn::Error::new(Span::call_site(), "missing `type Context`"))?;
let resolve_fn = resolve_fn
.ok_or_else(|| syn::Error::new(Span::call_site(), "missing `async fn resolve`"))?;
if resolve_fn.sig.asyncness.is_none() {
return Err(syn::Error::new_spanned(
resolve_fn.sig.fn_token,
"`resolve` must be an async fn",
));
}
let params: Vec<_> = resolve_fn.sig.inputs.iter().collect();
if params.len() != 2 {
return Err(syn::Error::new_spanned(
&resolve_fn.sig.inputs,
"`resolve` must take exactly two parameters: context and input references",
));
}
let ctx_name = param_ident(params[0])?;
let input_name = param_ident(params[1])?;View on GitHub (pinned to 0e4a05472f)
Solutions
- Add `async fn resolve(ctx: &Self::Context, input: &Self::Input) -> Self` to the impl block
- If you declared a custom `type Error`, make resolve return `Result<Self, Self::Error>`; otherwise return `Self` directly and the macro wraps it in `Ok(...)`
- Keep the method named exactly `resolve` with exactly two reference parameters
Example fix
// before
#[linked_state]
impl LinkedState for Post {
type Context = DbPool;
type Input = u32;
}
// after
#[linked_state]
impl LinkedState for Post {
type Context = DbPool;
type Input = u32;
async fn resolve(ctx: &DbPool, id: &u32) -> Self {
ctx.get_post(*id).await
}
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: the impl block must contain a method named `resolve`
// fn has_resolve_fn(imp: &syn::ItemImpl) -> bool {
// imp.items.iter().any(|i| matches!(i, syn::ImplItem::Fn(f) if f.sig.ident == "resolve"))
// } Prevention
- Write `async fn resolve(ctx: &Ctx, input: &Input) -> Self` with exactly two reference parameters and the `async` keyword
- Do not rename `resolve` — the macro only recognizes that exact identifier
- If you declared `type Error`, make the resolve body return `Result<Self, Self::Error>`; otherwise return `Self` and let the macro wrap it in `Ok`
When it happens
Trigger: An impl block annotated with `#[linked_state]` that declares the associated types but contains no `async fn resolve(...)` method — for example only `type Context` and `type Input`.
Common situations: Declaring the trait shape first and intending to add the resolver later, renaming `resolve` to something like `fetch` or `load` during development, or copying a partial example that omitted the method body.
Related errors
- missing `type Input`
- missing `type Context`
- only structs are supported
- this hook takes 2 arguments but 1 argument was supplied
- this hook takes 2 arguments but 1 argument was supplied
AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22).
Data as JSON: /api/errors/b02791bd1a7b480d.
Report an issue: GitHub.