leptos-rs/leptos · error
internal error: entered unreachable code
Error message
internal error: entered unreachable code
What it means
`rebuild()` for a reactive property binding (`value.rebuild(&mut state, &key)`) asserts the effect's previous property state is `Some` so the DOM property can be diffed. The `unreachable!()` panic means the effect re-ran with `prev == None` — the seeded `prev_value` was missing (effect created without a value, async value unresolved, or value already taken).
Source
Thrown at tachys/src/reactive_graph/property.rs:66
value.rebuild(&mut state, &key);
state
} else {
value.build(&el, &key)
}
})
}
fn rebuild(mut self, state: &mut Self::State, key: &str) {
let prev_value = state.take_value();
let key = key.to_owned();
*state = RenderEffect::new_with_value(
move |prev| {
let value = self.invoke();
if let Some(mut state) = prev {
value.rebuild(&mut state, &key);
state
} else {
unreachable!()
}
},
prev_value,
);
}
fn into_cloneable(self) -> Self::Cloneable {
self.into_shared()
}
fn into_cloneable_owned(self) -> Self::CloneableOwned {
self.into_shared()
}
}
macro_rules! property_reactive {
($name:ident, <$($gen:ident),*>, $v:ty, $( $where_clause:tt )*) =>
{View on GitHub (pinned to 32d20f6c9d)
Solutions
- Update signals only after the element and its attribute states are built/hydrated.
- Seed property effects with `RenderEffect::new_with_value` and an initial value in custom attribute implementations.
- Avoid resetting the same property state more than once.
- Upgrade to the latest leptos/tachys release where effect seeding is guaranteed.
Example fix
// before
*state = RenderEffect::new_with_value(move |prev| { /* expects Some */ }, prev_value);
// after
*state = RenderEffect::new_with_value(
move |prev: Option<PropState>| { /* Some guaranteed */ },
prev_value.unwrap_or_else(|| initial_prop_state(&key)),
); Defensive patterns
Strategy: fallback
Validate before calling
// Gate property updates on mounted state
let mounted = RwSignal::new(false);
create_effect(move |_| {
if !mounted.get() { return; }
let _ = prop_signal.get();
});
// mounted.set(true) after the element with prop: bindings mounts Type guard
fn prop_prev_present(prev: &Option<PropState>) -> bool { prev.is_some() } Try / catch
// Panic; use hook for diagnostics
std::panic::set_hook(Box::new(|info| {
if info.to_string().contains("entered unreachable code") {
leptos::logging::error!("property rebuild without prev: {info}");
}
})); Prevention
- Update prop: signals only after hydration/mount
- Avoid resetting property states twice during branch swaps
- Seed custom property effects with new_with_value
- Keep leptos workspace on a single version
When it happens
Trigger: A signal driving `prop:{name}={...}` updates while the property effect has no stored previous value: rebuild before build/hydrate committed state, async-seeded effect firing early, or a second rebuild after the value was taken by `reset`.
Common situations: Property bindings updated during SSR hydration before the initial value is stored; dynamic attribute sets (`{..props}` spread) whose state is reset on branch swap; mixing leptos crate versions in a workspace.
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/87d4408f5856a774.
Report an issue: GitHub.