leptos-rs/leptos · error
internal error: entered unreachable code
Error message
internal error: entered unreachable code
What it means
The `rebuild()` for a reactive `inner_html` binding creates/replaces a `RenderEffect` whose closure expects `Some(prev)` — the previous HTML string state used by `value.rebuild(&mut state)` to diff DOM inner HTML. `unreachable!()` means the effect ran with `prev == None`: the effect was seeded without a value (`prev_value` was `None`) or the value had been taken, so the diffing code had nothing to rebuild from.
Source
Thrown at tachys/src/reactive_graph/inner_html.rs:65
if let Some(mut state) = prev {
value.rebuild(&mut state);
state
} else {
value.build(&el)
}
})
}
fn rebuild(mut self, state: &mut Self::State) {
let prev_value = state.take_value();
*state = RenderEffect::new_with_value(
move |prev| {
let value = self.invoke();
if let Some(mut state) = prev {
value.rebuild(&mut state);
state
} else {
unreachable!()
}
},
prev_value,
);
}
fn into_cloneable(self) -> Self::Cloneable {
self.into_shared()
}
fn into_cloneable_owned(self) -> Self::CloneableOwned {
self.into_shared()
}
fn dry_resolve(&mut self) {
self.invoke();
}
View on GitHub (pinned to 32d20f6c9d)
Solutions
- Defer signal updates until after hydration/mount of the element completes.
- Seed the effect with `RenderEffect::new_with_value(f, initial_html)` when constructing state manually.
- Ensure `build`/`hydrate` runs before any `rebuild` on the same state.
- Update leptos/tachys to the latest 0.7.x where async-effect seeding was corrected.
Example fix
// before
let prev_value: Option<String> = None; // or taken
*state = RenderEffect::new_with_value(move |prev| { /* expects Some */ }, prev_value);
// after
let prev_value = Some(current_html);
*state = RenderEffect::new_with_value(move |prev: Option<String>| { /* Some guaranteed */ }, prev_value); Defensive patterns
Strategy: fallback
Validate before calling
// Only bind reactive inner_html after the element state exists
let mounted = RwSignal::new(false);
view! { <div inner_html={move || { if mounted.get() { html_signal.get() } else { String::new() } }} /> }
// set mounted.set(true) after mount Type guard
fn has_prev_html(prev: &Option<String>) -> bool { prev.is_some() } Try / catch
// Panic; capture with hook
std::panic::set_hook(Box::new(|info| {
if info.to_string().contains("unreachable") {
leptos::logging::error!("inner_html rebuild without prev state: {info}");
}
})); Prevention
- Avoid updating inner_html sources during hydration
- Ensure build/hydrate runs before rebuild for the same state
- Avoid sanitization-heavy dynamic HTML churn that triggers rebuilds pre-mount
- Update leptos/tachys together, never independently
When it happens
Trigger: Updating a signal driving `inner_html={...}` when the binding's effect previous value is `None` — typically after the state was built via a non-seeding path (`RenderEffect::new` in hydration) or `rebuild` called before `build` committed `prev_value`.
Common situations: Hydrating SSR content where the reactive `inner_html` fires before the hydration path stores its initial value; custom view code calling `rebuild` on a state constructed manually; leptos version mismatches between the view macro and tachys runtime.
Related errors
- internal error: entered unreachable code
- internal error: entered unreachable code
- internal error: entered unreachable code
- {location:?} expected context of type {type_name:?} to be pr
- Tried to access a reactive value that has already been dispo
AI-assisted analysis of leptos-rs/leptos@32d20f6c9d (2026-09-01).
Data as JSON: /api/errors/513eddfbba4ec2d9.
Report an issue: GitHub.