DioxusLabs/dioxus · error

Lazy value is not initialized. Make sure to call `initialize

Error message

Lazy value is not initialized. Make sure to call `initialize` before dereferencing.

What it means

Lazy is a OnceLock-based global used by dioxus-fullstack for server values. A Lazy created with Lazy::lazy()/Default has no constructor, so get()/Deref requires that set()/try_set() was called first; when the constructor is None and the value was never set, this expect panics. Lazy values with constructors self-initialize on first access, but bare lazy() values do not.

Source

Thrown at packages/fullstack/src/lazy.rs:98

            if self
                .started_initialization
                .swap(true, std::sync::atomic::Ordering::SeqCst)
            {
                self.value.wait();
                return Ok(());
            }

            // Otherwise, we need to initialize the value
            self.set(constructor().unwrap())?;
        }
        Ok(())
    }

    /// Get a reference to the value of the `Lazy` instance. This will block the current thread if the
    /// value is not yet initialized.
    pub fn get(&self) -> &T {
        if self.constructor.is_none() {
            return self.value.get().expect("Lazy value is not initialized. Make sure to call `initialize` before dereferencing.");
        };

        if self.value.get().is_none() {
            self.initialize().expect("Failed to initialize lazy value");
        }

        self.value.get().unwrap()
    }
}

impl<T: Send + Sync + 'static> Default for Lazy<T> {
    fn default() -> Self {
        Self::lazy()
    }
}

impl<T: Send + Sync + 'static> std::ops::Deref for Lazy<T> {
    type Target = T;

View on GitHub (pinned to 393d190a80)

Solutions

  1. Initialize the Lazy during server setup: lazy.set(value) or try_set(value) before any access
  2. Create it with Lazy::new(constructor) instead of Lazy::lazy() so it self-initializes on first get()
  3. Only deref the Lazy inside a running dioxus::serve app where setup guarantees initialization
  4. In tests, call set()/initialize() in the harness before touching code that dereferences it

Example fix

// before
static DB: Lazy<Db> = Lazy::lazy();
fn handler() { DB.query(...); } // panics: never set
// after
static DB: Lazy<Db> = Lazy::new(|| async { connect().await });
// or: DB.set(connect_now()) during dioxus::serve setup
Defensive patterns

Strategy: validation

Validate before calling

// Expose an accessor instead of raw deref:
pub fn db() -> Option<&'static Db> {
    DB.try_get()
}
// or ensure setup ran:
fn ensure_initialized(lazy: &Lazy<Db>) -> Result<(), CapturedError> { lazy.initialize() }

Prevention

When it happens

Trigger: Dereferencing a Lazy created via Lazy::lazy() that was never initialized: accessing a fullstack server context or a Lazy global (e.g. a connection pool) outside of the dioxus::serve setup that should call set(), or forgetting the initialization step in the server config callback.

Common situations: Unit tests calling server helpers that deref a Lazy without booting the server; a binary path that never runs launch setup; refactoring that moves set() behind a disabled feature or config branch.

Related errors


AI-assisted analysis of DioxusLabs/dioxus@393d190a80 (2026-08-16). Data as JSON: /api/errors/5f5fc57edc077b95. Report an issue: GitHub.