SeaQL/sea-orm · error
index out of bounds: the ActiveHasMany is NotSet (index: {in
Error message
index out of bounds: the ActiveHasMany is NotSet (index: {index}) What it means
The `Index<usize>` implementation for `ActiveHasMany<E>` panics when the collection is `NotSet`, because there are no child models to index — the relation was never populated on this active model. `Replace`/`Append` variants delegate to the inner vector's own bounds check. The message reports the requested index.
Source
Thrown at src/entity/active_model_ex.rs:430
}
}
impl<E: EntityTrait> From<ActiveHasMany<E>> for Option<Vec<E::ActiveModelEx>> {
fn from(value: ActiveHasMany<E>) -> Self {
match value {
ActiveHasMany::NotSet => None,
ActiveHasMany::Replace(models) | ActiveHasMany::Append(models) => Some(models),
}
}
}
impl<E: EntityTrait> Index<usize> for ActiveHasMany<E> {
type Output = E::ActiveModelEx;
fn index(&self, index: usize) -> &Self::Output {
match self {
ActiveHasMany::NotSet => {
panic!("index out of bounds: the ActiveHasMany is NotSet (index: {index})")
}
ActiveHasMany::Replace(models) | ActiveHasMany::Append(models) => models.index(index),
}
}
}
impl<E: EntityTrait> IndexMut<usize> for ActiveHasMany<E> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match self {
ActiveHasMany::NotSet => {
panic!("index out of bounds: the ActiveHasMany is NotSet (index: {index})")
}
ActiveHasMany::Replace(models) | ActiveHasMany::Append(models) => {
models.index_mut(index)
}
}
}
}View on GitHub (pinned to e29bcd1b41)
Solutions
- Load the relation first: `Entity::load().with(child::Entity)` or call the relation setter before indexing.
- Check `matches!(am.children, ActiveHasMany::NotSet)` (or an `is_not_set`/`is_set` helper) before indexing.
- Use the collection's accessor/iterator methods that return `Option` instead of `Index`.
- Initialize children with `Replace(vec![])` if an empty collection is valid for your flow.
Example fix
// before
let first = &user.posts[0]; // panics if posts NotSet
// after
if !user.posts.is_not_set() {
let first = &user.posts[0];
} Defensive patterns
Strategy: validation
Validate before calling
let first = match &user.posts {
ActiveHasMany::NotSet => return Err(anyhow!("posts not loaded")),
ActiveHasMany::Replace(m) | ActiveHasMany::Append(m) => m.first(),
}; Type guard
fn posts_loaded<E: EntityTrait>(posts: &ActiveHasMany<E>) -> bool {
!matches!(posts, ActiveHasMany::NotSet)
} Try / catch
std::panic::catch_unwind(|| user.posts[0].clone()) // prefer the match/guard above
Prevention
- Load relations with .with(child::Entity) before indexing.
- Treat NotSet as 'not loaded', not 'empty' — check before indexing.
- Prefer .first()/.get(i) style accessors returning Option.
- Initialize relations with Replace(vec![]) when an empty set is valid.
When it happens
Trigger: Evaluating `active_model.children[0]` (or any index) when the has-many relation was never set via `set_children`/`Replace`/`Append` after building the active model.
Common situations: Loading an entity without `.with(child::Entity)` and then indexing its relation; assuming relations come pre-populated from a find query; constructing a fresh ActiveModel and reading children before pushing any.
Related errors
- index out of bounds: the ActiveHasMany is NotSet (index: {in
- index out of bounds: the HasMany is Unloaded (index: {index}
- called `BelongsTo::unwrap()` on an `Unloaded` value
- called `BelongsTo::unwrap()` on a `Loaded(None)` value
- index out of bounds: the HasMany is Unloaded (index: {index}
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/836a627864083b31.
Report an issue: GitHub.