yewstack/yew · critical
resolver not set on server-side LinkProvider
Error message
resolver not set on server-side LinkProvider
What it means
On SSR builds, LinkContextInner::resolve_local (packages/yew-link/src/lib.rs:394) unwraps the provider's optional resolver with .expect. The resolver is only populated when the server-side <LinkProvider> was given a resolver prop (LinkProviderProps.resolver, line 444); on wasm it is ignored. If a server render calls use_linked_state through a LinkProvider that has no resolver, this panic fires.
Source
Thrown at packages/yew-link/src/lib.rs:394
Some(err_val) => {
let e: T::Error = serde_json::from_value(err_val)
.map_err(|e| LinkError::Internal(e.to_string()))?;
Err(LinkError::Resolve(e))
}
None => Err(LinkError::Internal("unknown error".into())),
},
}
}
#[cfg(feature = "ssr")]
async fn resolve_local<T: LinkedState>(
&self,
input: &T::Input,
) -> Result<T, LinkError<T::Error>> {
let resolver = self
.resolver
.as_ref()
.expect("resolver not set on server-side LinkProvider");
let req = LinkRequest {
type_key: T::TYPE_KEY.to_string(),
input: serde_json::to_value(input).map_err(|e| LinkError::Internal(e.to_string()))?,
};
match resolver.resolve_request(&req).await {
Ok(val) => serde_json::from_value(val).map_err(|e| LinkError::Internal(e.to_string())),
Err(err_val) => {
let e: T::Error = serde_json::from_value(err_val)
.map_err(|e| LinkError::Internal(e.to_string()))?;
Err(LinkError::Resolve(e))
}
}
}
}
/// Wrapper so [`Resolver`] can be passed as a component prop.
///
/// Uses `Arc` internally so it is `Send` (required by `ServerRenderer::with_props`).View on GitHub (pinned to 0e4a05472f)
Solutions
- Pass a ResolverProp to LinkProvider in the SSR tree: <LinkProvider resolver={ResolverProp(resolver)} endpoint={...}>{children}</LinkProvider>
- Keep separate provider props for server and client: server = resolver (endpoint ignored), client = endpoint
- If you cannot resolve locally on the server, disable the ssr feature so the hook does not take the resolve_local path
Example fix
// before
let props = LinkProviderProps { children, endpoint: AttrValue::from("/api/link"), resolver: None, cache_capacity: 64 };
// after
let resolver = Resolver::new(|req| Box::pin(async move { resolve_link(req).await }));
let props = LinkProviderProps { children, endpoint: AttrValue::from("/api/link"), resolver: Some(resolver.into()), cache_capacity: 64 }; Defensive patterns
Strategy: validation
Validate before calling
// build SSR provider props with a resolver, fail fast if it is missing
let resolver = Resolver::new(|req| Box::pin(async move { resolve_link(req).await }));
let props = LinkProviderProps {
children: Children::new(vec![/* app */]),
endpoint: AttrValue::from("/api/link"),
resolver: Some(resolver.into()),
cache_capacity: 64,
};
debug_assert!(props.resolver.is_some(), "SSR LinkProvider needs a resolver"); Type guard
// narrow on the prop before rendering the server tree
fn has_ssr_resolver(props: &LinkProviderProps) -> bool { #[cfg(feature = "ssr")] { props.resolver.is_some() } #[cfg(not(feature = "ssr"))] { true } } Prevention
- Maintain separate provider props for server (resolver) and client (endpoint)
- Add a debug_assert on the resolver before starting ServerRenderer
- Run one SSR smoke test per app entry so a misconfigured provider panics in CI, not production
When it happens
Trigger: Rendering with the ssr feature enabled (ServerRenderer) while <LinkProvider> only received an endpoint and no ResolverProp; building a LinkProviderProps by hand and leaving resolver as None; feature-flag drift where the server build takes the ssr branch of resolve_local.
Common situations: Configuring LinkProvider once for the client (endpoint only) and reusing those props for the server renderer; adding yew-link SSR to an existing client app and missing the server-side resolver wiring; upgrading yew-link where resolver became a required-for-SSR prop.
Related errors
- use_linked_state requires a LinkProvider
- this hook takes 2 arguments but 1 argument was supplied
- this hook takes 2 arguments but 1 argument was supplied
- failed to find worker context
- unkeyed child in fully keyed list
AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22).
Data as JSON: /api/errors/3a25e0d3db5c0a48.
Report an issue: GitHub.