SeaQL/sea-orm · error

Must be valid

Error message

Must be valid

What it means

`delete_by_id` builds a Delete ActiveModel from the given id value and validates it with `.validate().expect("Must be valid")` (src/entity/base_entity.rs:1085). Validation should always pass for a properly constructed key-backed delete, so this panic indicates the constructed ActiveModel failed validation — e.g. a key value whose type doesn't match the primary key column type.

Source

Thrown at src/entity/base_entity.rs:1085

    /// #
    /// # Ok(())
    /// # }
    /// ```
    fn delete_by_id<T>(values: T) -> ValidatedDeleteOne<Self>
    where
        T: Into<<Self::PrimaryKey as PrimaryKeyTrait>::ValueType>,
    {
        let mut am = Self::ActiveModel::default();
        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();
                am.set(col, v);
            } else {
                unreachable!("primary key arity mismatch");
            }
        }
        Delete::one(am).validate().expect("Must be valid")
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_delete_by_id_1() {
        use crate::tests_cfg::cake;
        use crate::{DbBackend, entity::*, query::*};
        assert_eq!(
            cake::Entity::delete_by_id(1)
                .build(DbBackend::Sqlite)
                .to_string(),
            r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
        );
    }

    #[test]

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Call delete_by_id with a value matching the primary key's declared type exactly (e.g. i64 for SQLite-generated entities).
  2. For composite keys, pass the full tuple in the declared column order.
  3. Convert through `delete_by_id(key.into_value())`-style helpers instead of hand-building values.
  4. If validation rejects a correct key, replace with `Entity::delete_by_id` alternative: build the ActiveModel yourself and call `Delete::one(am).exec(db)` to get a DbErr instead of a panic.

Example fix

// before
entity::Entity::delete_by_id("42".to_string()).exec(db).await?;
// after (primary key is i64)
entity::Entity::delete_by_id(42i64).exec(db).await?;
Defensive patterns

Strategy: validation

Validate before calling

// confirm the id type matches the primary key before delete_by_id
let pk_type = <entity::Entity as EntityTrait>::PrimaryKey::iter().next().unwrap().value_type();
assert!(matches!(id, v if std::mem::discriminant(&v) == std::mem::discriminant(&pk_type)));

Type guard

fn id_matches_pk(id: &Value) -> bool {
    use sea_orm::Value;
    matches!(id, Value::BigInt(_) | Value::TinyInt(_) | Value::SmallInt(_) | Value::Int(_))
}

Try / catch

// avoid the expect by building the delete yourself to get a DbErr
let mut am = entity::ActiveModel { id: sea_orm::ActiveValue::Set(42), ..Default::default() };
entity::Entity::delete(am).exec(db).await?;

Prevention

When it happens

Trigger: Calling `Entity::delete_by_id()` with a value that sets a primary key column violating validation rules (wrong value type pushed into the ActiveModel, or composite key helper mismatch) — validation then fails and the expect panics.

Common situations: Passing a wrongly-typed id (string vs integer) that coerces into the ActiveModel but fails column validation; composite keys where the value shape does not match column order; sea-orm-cli-generated i64 keys vs code supplying i32 with mismatched DeriveValueType wrappers.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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