SeaQL/sea-orm · warning

called `BelongsTo::unwrap()` on a `Loaded(None)` value

Error message

called `BelongsTo::unwrap()` on a `Loaded(None)` value

What it means

BelongsTo<Option<E>>::unwrap() was called on a Loaded(None) value: the relation was loaded but no related parent row exists (dangling/deleted foreign key). unwrap() refuses to fabricate a model for an absent parent, so it panics; absence of the parent is a legitimate state that callers must handle rather than force-open.

Source

Thrown at src/entity/compound/belongs_to.rs:188

        }
    }

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

    /// # 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 `BelongsTo::unwrap()` on an `Unloaded` value"),
            Self::Loaded(None) => panic!("called `BelongsTo::unwrap()` on a `Loaded(None)` value"),
        }
    }
}

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

impl<E> BelongsTo<Option<E>>

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Match on the Option instead of unwrapping: if let Some(parent) = relation value
  2. Use try_unwrap() and handle the missing-relation case
  3. Make the foreign key NOT NULL in the schema if a parent is truly required

Example fix

// before
let parent = post.author.unwrap();
// after
let parent = post.author.try_unwrap()?.unwrap_or_default_parent();
Defensive patterns

Strategy: fallback

Validate before calling

if matches!(post.author, BelongsTo::Loaded(None)) { /* no parent — handle */ }

Type guard

fn has_parent<E>(b: &BelongsTo<Option<E>>) -> bool { matches!(b, BelongsTo::Loaded(Some(_))) }

Try / catch

let parent = post.author.try_unwrap()?.unwrap_or_default();

Prevention

When it happens

Trigger: Calling .unwrap() on a loaded optional belongs_to whose foreign key is NULL or points to a deleted row (loaded to None).

Common situations: Nullable foreign keys where the row legitimately has no parent; the parent row was deleted after insert; NOT NULL assumption broken by schema change.

Related errors


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