SeaQL/sea-orm · critical

Already checked arity

Error message

Already checked arity

What it means

This panic is thrown in `EntityTrait::primary_key_identity()` when the primary key iterator returns `None` even though the `PrimaryKeyArity` trait declared the key has more columns. It is an internal invariant: the compile-time ARITY constant must exactly match the number of columns in the `PrimaryKey` enum. The message 'Already checked arity' reflects that the match on ARITY was supposed to guarantee `cols.next()` succeeds that many times.

Source

Thrown at sea-orm-sync/src/entity/base_entity.rs:341

        let mut keys = Self::PrimaryKey::iter();
        for v in values.into().into_value_tuple() {
            if let Some(key) = keys.next() {
                let col = key.into_column();
                select = select.filter(col.eq(v));
            } else {
                unreachable!("primary key arity mismatch");
            }
        }
        select
    }

    /// Get primary key as Identity
    fn primary_key_identity() -> Identity {
        let mut cols = Self::PrimaryKey::iter();
        macro_rules! next {
            () => {
                cols.next()
                    .expect("Already checked arity")
                    .into_column()
                    .as_column_ref()
                    .1
            };
        }
        match <<Self::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
            1 => {
                let s1 = next!();
                Identity::Unary(s1)
            }
            2 => {
                let s1 = next!();
                let s2 = next!();
                Identity::Binary(s1, s2)
            }
            3 => {
                let s1 = next!();
                let s2 = next!();

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Regenerate the entity with sea-orm-cli so the PrimaryKey enum and its ValueType arity match the table schema.
  2. If hand-written, make the PrimaryKey ValueType match the column count: one column uses the id type, composite keys use a tuple like (i32, i32).
  3. Ensure `PrimaryKeyTrait` is implemented via `#[derive(Iden)]`/DerivePrimaryKey so ARITY is derived, not manually specified with the wrong number.

Example fix

// before
pub enum PrimaryKey { Id } // but ValueType declared as (i32, i32)
// after
#[derive(EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey { Id, Version }
// ValueType is derived as (i32, i32) matching two columns
Defensive patterns

Strategy: validation

Validate before calling

let arity = <MyEntity::PrimaryKey as PrimaryKeyTrait>::ValueType::arity();
let col_count = MyEntity::PrimaryKey::iter().count();
assert_eq!(arity, col_count, "PrimaryKey enum/ValueType arity mismatch");

Type guard

fn has_consistent_pk<E: EntityTrait>() -> bool {
    E::PrimaryKey::iter().count() == <<E::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY
}

Prevention

When it happens

Trigger: Occurs when a hand-written entity declares a `PrimaryKey` enum whose number of variants disagrees with the `PrimaryKeyArity` implementation for its `ValueType` (e.g. composite key misdeclared as single-column), or when the PrimaryKey iter() impl and the ARITY constant are inconsistent.

Common situations: Developers manually writing entity definitions instead of using sea-orm-cli codegen, refactoring a table from a single-column to a composite primary key without updating `ValueType` to a tuple, or upgrading SeaORM versions where arity derives changed.

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