SeaQL/sea-orm · error
item is a full model
Error message
item is a full model
What it means
`establish_links` unwraps `leftover.get_primary_key_value()` with `.expect("item is a full model")` (src/entity/active_model.rs:1296). The precondition is that every leftover junction row is a fully-loaded Model (all columns present, including primary key). Panicking means a model without a complete primary key value was treated as a full model — normally impossible when models come straight from a DB query.
Source
Thrown at src/entity/active_model.rs:1296
let via_key = get_key_from_active_model(&right.from_col, &via)?;
if !leftover.iter().any(|t| t.1 == via_key) {
// if not already exist, save for insert
via_models.push(via);
}
if delete_leftover {
all_keys.insert(via_key);
}
}
if delete_leftover {
let mut to_delete = Vec::new();
let mut to_delete_am = Vec::new();
for (leftover, key) in leftover {
if !all_keys.contains(&key) {
to_delete.push(
leftover
.get_primary_key_value()
.expect("item is a full model"),
);
to_delete_am.push(leftover);
}
}
if !to_delete.is_empty() {
// run before_delete hooks
for am in to_delete_am.clone() {
am.before_delete(db).await?;
}
if db.support_returning() {
let deleted = J::delete_many()
.filter_by_value_tuples(&to_delete, db.get_database_backend())
.exec_with_returning(db)
.await?;
// run after_delete hooks with the returned value if possible
for am in deleted {
let am = am.into_active_model();
let _ = am.after_delete(db).await?;View on GitHub (pinned to e29bcd1b41)
Solutions
- Ensure the junction models passed through establish_links come from a database select so primary keys are populated.
- Do not construct Models by hand for link sync; use ActiveModels.
- Check that the junction entity's primary key is correctly declared (composite, auto_increment=false).
- If using IntoActiveModel conversions, verify all PK columns were Set before conversion.
Example fix
// before (hand-built model missing PK)
let j = junction::Model { post_id: 1, /* tag_id missing */ };
// after
let j = junction::Entity::find_by_id((post.id, tag.id)).one(db)?.unwrap(); Defensive patterns
Strategy: validation
Validate before calling
// ensure leftover models have complete primary keys before link sync
for m in leftovers {
assert!(m.get_primary_key_value().is_some(), "junction model missing PK");
} Type guard
fn is_full_model<M: ModelTrait>(m: &M) -> bool {
m.get_primary_key_value().is_some()
} Prevention
- Load junction models from the DB rather than constructing them in code
- Declare junction primary keys correctly (composite, auto_increment=false)
- Avoid IntoActiveModel round-trips that drop Set primary keys
When it happens
Trigger: Calling `insert_many`/link-establishing APIs (e.g. `save` with delete_leftover semantics) where a leftover junction Model lacks primary key values — e.g. an ActiveModel converted to Model prematurely, or a Model constructed in code with None/zeroed keys.
Common situations: Programmatically constructing junction Models instead of loading them; custom ORM behavior overrides that return partially-populated models into establish_links.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/c8d00218258533b8.
Report an issue: GitHub.