SeaQL/sea-orm · error

called `HasOne::unwrap()` on an `Unloaded` value

Error message

called `HasOne::unwrap()` on an `Unloaded` value

What it means

unwrap() on HasOne<E> only works when the relation was eagerly loaded and a row was found. It fires here because the variant is Unloaded, meaning the relation was never fetched (no .with(...)/.find_also_related(...) was used before accessing it), so there is no model to return. This is a programming/API-usage error, not a data error.

Solutions

  1. Eagerly load the relation before unwrapping, e.g. Entity::load().with(parent::Entity).one(db) so the HasOne becomes Loaded(Some(..)).
  2. Match on the HasOne value and handle Unloaded and Loaded(None) explicitly instead of unwrapping.
  3. Use into_option() or take(), which return None for Unloaded/Loaded(None) instead of panicking.
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at sea-orm-sync/src/entity/compound/has_one.rs:77 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10). Data as JSON: /api/errors/1a889b6aeeb003d7. Report an issue: GitHub.

Appendix: source

Thrown at sea-orm-sync/src/entity/compound/has_one.rs:77

    pub fn into_option(self) -> Option<E::ModelEx> {
        match self {
            Self::Loaded(Some(model)) => Some(*model),
            Self::Unloaded | Self::Loaded(None) => None,
        }
    }

    /// Take ownership of the contained Model, if loaded, leaving `Unloaded` in place.
    pub fn take(&mut self) -> Option<E::ModelEx> {
        std::mem::take(self).into_option()
    }

    /// # Panics
    ///
    /// Panics if called on an `Unloaded` or `Loaded(None)` value.
    pub fn unwrap(self) -> E::ModelEx {
        match self {
            Self::Loaded(Some(model)) => *model,
            Self::Unloaded => panic!("called `HasOne::unwrap()` on an `Unloaded` value"),
            Self::Loaded(None) => panic!("called `HasOne::unwrap()` on a `Loaded(None)` value"),
        }
    }
}

impl<E> HasOne<E>
where
    E: EntityTrait,
    E::ActiveModelEx: From<E::ModelEx>,
{
    pub fn into_active_model(self) -> ActiveHasOne<E> {
        match self {
            Self::Loaded(Some(model)) => ActiveHasOne::set(Some(*model)),
            Self::Unloaded | Self::Loaded(None) => ActiveHasOne::NotSet,
        }
    }
}

View on GitHub (pinned to e29bcd1b41)