leptos-rs/leptos · error

rendering A to HTML without filling it

Error message

rendering A to HTML without filling it

What it means

Mirror of the B-side panic: when show_b is false, EitherKeepAliveState renders self.a, which must contain the A view. This panic means the state says branch A is shown but the A slot is None. The Option is an internal invariant — exactly one side is filled — and rendering hit the empty side.

Source

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

        buf: &mut String,
        position: &mut Position,
        escape: bool,
        mark_branches: bool,
        extra_attrs: Vec<AnyAttribute>,
    ) {
        if self.show_b {
            self.b
                .expect("rendering B to HTML without filling it")
                .to_html_with_buf(
                    buf,
                    position,
                    escape,
                    mark_branches,
                    extra_attrs,
                );
        } else {
            self.a
                .expect("rendering A to HTML without filling it")
                .to_html_with_buf(
                    buf,
                    position,
                    escape,
                    mark_branches,
                    extra_attrs,
                );
        }
    }

    fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
        self,
        buf: &mut StreamBuilder,
        position: &mut Position,
        escape: bool,
        mark_branches: bool,
        extra_attrs: Vec<AnyAttribute>,
    ) where

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Refill the a slot before flipping showing_b back to false.
  2. Construct the state through its normal API so the active view is always stored.
  3. Add a debug assertion in your code that (showing_b == b.is_some()) && (!showing_b || a.is_none()) before rendering.

Example fix

// before
state.showing_b = false; // a is still None
state.to_html_with_buf(...); // panics
// after
state.a = Some(view_a);
state.showing_b = false;
state.to_html_with_buf(...);
Defensive patterns

Strategy: validation

Validate before calling

if !state.showing_b && state.a.is_none() {
    return Err("A branch flag set but a view is None");
}
state.to_html_with_buf(&mut buf, position, escape, mark_branches, extra_attrs);

Type guard

fn a_side_filled<A, B>(state: &EitherKeepAliveState<A, B>) -> bool {
    state.showing_b || true /* replace with a.is_some() accessor */
}

Try / catch

std::panic::catch_unwind(|| state.to_html_with_buf(&mut buf, position, escape, mark_branches, extra_attrs))
    .inspect_err(|_| eprintln!("EitherKeepAliveState had unfilled A branch during SSR"));

Prevention

When it happens

Trigger: Calling to_html_with_buf on an EitherKeepAliveState with show_b == false and a == None — state constructed/mutated without filling the A view, then server-rendered.

Common situations: Manual construction of EitherKeepAliveState for SSR tests; a state that was moved into branch B (a set to None) but whose show_b flag was reset to false without re-filling a.

Related errors


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