leptos-rs/leptos · error

B was not present

Error message

B was not present

What it means

EitherKeepAliveState::unmount unmounts the stored B view when showing_b is true, unwrapping self.b. This panic means the client-side state claims branch B is mounted but the B view was never stored (b is None), so there is nothing to unmount. It indicates the state was built or mutated outside the library's mount/rebuild flow.

Source

Thrown at tachys/src/view/either.rs:718

    }

    fn into_owned(self) -> Self::Owned {
        EitherKeepAlive {
            a: self.a.map(|a| a.into_owned()),
            b: self.b.map(|b| b.into_owned()),
            show_b: self.show_b,
        }
    }
}

impl<A, B> Mountable for EitherKeepAliveState<A, B>
where
    A: Mountable,
    B: Mountable,
{
    fn unmount(&mut self) {
        if self.showing_b {
            self.b.as_mut().expect("B was not present").unmount();
        } else {
            self.a.as_mut().expect("A was not present").unmount();
        }
    }

    fn mount(
        &mut self,
        parent: &crate::renderer::types::Element,
        marker: Option<&crate::renderer::types::Node>,
    ) {
        if self.showing_b {
            self.b
                .as_mut()
                .expect("B was not present")
                .mount(parent, marker);
        } else {
            self.a
                .as_mut()

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Only unmount states that went through mount(); track a mounted flag yourself for idempotent teardown.
  2. Fill b = Some(view_b) whenever showing_b = true in hand-built state.
  3. Avoid mutating EitherKeepAliveState fields directly; use the EitherKeepAlive view's update path.

Example fix

// before
if !state.mounted { state.unmount(); } // panics when b is None
// after
if state.mounted && state.b.is_some() { state.unmount(); state.mounted = false; }
Defensive patterns

Strategy: validation

Validate before calling

if state.showing_b && state.b.is_some() {
    state.unmount();
}

Type guard

fn can_unmount<A, B>(state: &EitherKeepAliveState<A, B>) -> bool {
    if state.showing_b { true /* b.is_some() */ } else { true /* a.is_some() */ }
}

Try / catch

std::panic::catch_unwind(|| state.unmount())
    .inspect_err(|_| eprintln!("attempted to unmount an EitherKeepAliveState with unfilled active branch"));

Prevention

When it happens

Trigger: Calling unmount on an EitherKeepAliveState with showing_b == true but b == None — e.g. a state created with an empty B slot, or double-unmount after a switch cleared b.

Common situations: Calling unmount twice on the same state; manually constructing EitherKeepAliveState for client-side use; reactive teardown running after the branch already switched (b moved out).

Related errors


AI-assisted analysis of leptos-rs/leptos@32d20f6c9d (2026-09-01). Data as JSON: /api/errors/541d0fcbd67c5c43. Report an issue: GitHub.