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

  1. Pass a ResolverProp to LinkProvider in the SSR tree: <LinkProvider resolver={ResolverProp(resolver)} endpoint={...}>{children}</LinkProvider>
  2. Keep separate provider props for server and client: server = resolver (endpoint ignored), client = endpoint
  3. 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

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


AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22). Data as JSON: /api/errors/3a25e0d3db5c0a48. Report an issue: GitHub.