SeaQL/sea-orm · critical

Already checked arity

Error message

Already checked arity

What it means

`ModelTrait::get_primary_key_value()` iterates the entity's `PrimaryKey` columns and expects exactly as many columns as `PrimaryKeyArity::ARITY` declares. The panic fires when the iterator runs dry before ARITY is satisfied, i.e. the compile-time arity constant disagrees with the actual number of primary key column variants.

Source

Thrown at sea-orm-sync/src/entity/model.rs:89

        find_linked_recursive(initial_query, link)
    }

    /// Delete a model
    fn delete<'a, A, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
    where
        Self: IntoActiveModel<A>,
        C: ConnectionTrait,
        A: ActiveModelTrait<Entity = Self::Entity> + ActiveModelBehavior + 'a,
    {
        self.into_active_model().delete(db)
    }

    /// Get the primary key value of the Model
    fn get_primary_key_value(&self) -> ValueTuple {
        let mut cols = <Self::Entity as EntityTrait>::PrimaryKey::iter();
        macro_rules! next {
            () => {
                self.get(cols.next().expect("Already checked arity").into_column())
            };
        }
        match <<<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
            1 => {
                let s1 = next!();
                ValueTuple::One(s1)
            }
            2 => {
                let s1 = next!();
                let s2 = next!();
                ValueTuple::Two(s1, s2)
            }
            3 => {
                let s1 = next!();
                let s2 = next!();
                let s3 = next!();
                ValueTuple::Three(s1, s2, s3)
            }

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Regenerate the entity from the database schema with sea-orm-cli.
  2. Align the PrimaryKey enum variants and ValueType tuple length (1, 2, or 3 columns).
  3. Run entity unit tests after any schema change to catch arity drift before runtime.

Example fix

// before
#[derive(EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey { Id } // table actually has (Id, TenantId)
// after
#[derive(EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey { Id, TenantId }
Defensive patterns

Strategy: validation

Validate before calling

let col_count = <MyEntity as EntityTrait>::PrimaryKey::iter().count();
let arity = <<MyEntity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType::arity();
assert_eq!(col_count, arity, "entity primary key arity drift");

Type guard

fn model_pk_consistent<M: ModelTrait>() -> bool {
    <<M::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType::arity()
        == <M::Entity as EntityTrait>::PrimaryKey::iter().count()
}

Prevention

When it happens

Trigger: Calling `.get_primary_key_value()` (directly or via save/delete helpers) on a Model whose entity's PrimaryKey enum has fewer variants than the declared ARITY, typically due to a hand-edited or stale entity definition.

Common situations: Migrations that added a primary key column while the generated entity was not refreshed; copying an entity module and editing columns without regenerating; composite key tables modeled with a single-column ValueType.

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/7e0acc82efb59959. Report an issue: GitHub.