leptos-rs/leptos · error

no reactive owner

Error message

no reactive owner

What it means

OwnedView::new tries to attach the given view to the currently active reactive Owner via Owner::current(). If no owner is in scope, it panics with 'no reactive owner'. The library throws it because an owned view must be cleaned up by some owner; without one it would leak or dangle.

Source

Thrown at tachys/src/reactive_graph/owned.rs:21

    hydration::Cursor,
    prelude::Mountable,
    ssr::StreamBuilder,
    view::{add_attr::AddAnyAttr, Position, PositionState, Render, RenderHtml},
};
use reactive_graph::{computed::ScopedFuture, owner::Owner};
use std::mem;

/// A view wrapper that sets the reactive [`Owner`] to a particular owner whenever it is rendered.
#[derive(Debug, Clone)]
pub struct OwnedView<T> {
    owner: Owner,
    view: T,
}

impl<T> OwnedView<T> {
    /// Wraps a view with the current owner.
    pub fn new(view: T) -> Self {
        let owner = Owner::current().expect("no reactive owner");
        Self { owner, view }
    }

    /// Wraps a view with the given owner.
    pub fn new_with_owner(view: T, owner: Owner) -> Self {
        Self { owner, view }
    }
}

/// Retained view state for an [`OwnedView`].
#[derive(Debug, Clone)]
pub struct OwnedViewState<T>
where
    T: Mountable,
{
    // note: the drop order of the fields matters here
    // dropping `state` before `owner` ensures that cleanups happen
    // from the bottom up: i.e., the child state is dropped before

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Wrap the code in a reactive scope/root so an Owner exists (e.g. inside a component or Owner::new().run(...))
  2. Use OwnedView::new_with_owner with an explicitly captured Owner
  3. Spawn async work via leptos facilities that carry the owner instead of raw threads/spawn
  4. In tests, initialize a root owner before constructing views

Example fix

// before
let owned = OwnedView::new(view); // panics outside scope
// after
let owner = Owner::current().expect("setup owner first");
let owned = OwnedView::new_with_owner(view, owner);
Defensive patterns

Strategy: fallback

Validate before calling

fn has_owner() -> bool { Owner::current().is_some() }
// call before: if !has_owner() { /* don't build OwnedView */ }

Type guard

fn current_owner() -> Option<Owner> { Owner::current() }

Try / catch

// panic-based; prefer explicit check over catch:
match Owner::current() {
    Some(owner) => OwnedView::new_with_owner(view, owner),
    None => { /* log & skip, or initialize a root scope first */ }
}

Prevention

When it happens

Trigger: Creating an OwnedView outside any reactive ownership context: before the reactive runtime is initialized, inside a plain thread/task without entering an owner, or after the owning scope has been dropped.

Common situations: Building views in a tokio spawn without owner context; tests that construct views without a root/run-in-scope wrapper; calling view constructors during SSR teardown; using the API in non-Leptos app code.

Related errors


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