loco-rs/loco · error

Type mismatch in RefGuard

Error message

Type mismatch in RefGuard

What it means

A defensive `expect` panic in Loco's shared-store `RefGuard` access. The guard is only supposed to be created for a type after looking it up by `TypeId`, so a downcast failure means the internal type-map invariant was violated — the stored value's concrete type doesn't match `T`.

Solutions

  1. Check that the exact type you pass when reading the shared store matches the one inserted (including wrappers like `Arc<...>`)
  2. Insert the value through the typed API before creating a RefGuard for it
  3. If it reproduces with correct usage, file a loco-rs issue — this indicates an internal invariant violation

Example fix

// before
let cfg = ctx.shared_store.get::<Config>();
// after
let cfg = ctx.shared_store.get::<Arc<Config>>(); // type actually stored
Defensive patterns

Strategy: type-guard

Type guard

fn try_get<T: Any + Send + Sync>(store: &SharedStore) -> Option<RefGuard<T>> {
    store.try_get::<T>()
}

Prevention

When it happens

Trigger: Accessing `ctx.shared_store` with a type parameter `T` that was never stored under that `TypeId`, or a bug in the RefGuard construction path storing a mismatched concrete type.

Common situations: Requesting a shared-store value with a slightly different type than inserted (e.g. `Arc<Config>` vs `Config`); framework-level bugs after refactors of the shared_store container.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of loco-rs/loco@23639d1e36 (2026-09-12). Data as JSON: /api/errors/45988f544fd88b3e. Report an issue: GitHub.

Appendix: source

Thrown at src/app.rs:243

// A wrapper around DashMap's Ref type that erases the exact type
// but provides deref to the target type
pub struct RefGuard<'a, T: 'static + Send + Sync> {
    inner: dashmap::mapref::one::Ref<'a, TypeId, Box<dyn Any + Send + Sync>>,
    _phantom: std::marker::PhantomData<&'a T>,
}

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

    fn deref(&self) -> &Self::Target {
        // This is safe because we only create a RefGuard for a specific type
        // after looking it up by its TypeId
        #[allow(clippy::coerce_container_to_any)]
        self.inner
            .value()
            .downcast_ref::<T>()
            .expect("Type mismatch in RefGuard")
    }
}

/// Represents the application context for a web server.
///
/// This struct encapsulates various components and configurations required by
/// the web server to operate. It is typically used to store and manage shared
/// resources and settings that are accessible throughout the application's
/// lifetime.
#[derive(Clone, FromRef)]
#[allow(clippy::module_name_repetitions)]
#[non_exhaustive]
pub struct AppContext {
    /// The environment in which the application is running.
    pub environment: Environment,
    #[cfg(feature = "with-db")]
    /// A database connection used by the application.
    pub db: DatabaseConnection,

View on GitHub (pinned to 23639d1e36)