{"record":{"id":"ae1d52ef2011249c","repo":"SeaQL/sea-orm","slug":"trait-bound-ensured-arity","errorCode":null,"errorMessage":"trait bound ensured arity","messagePattern":"trait bound ensured arity","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sea-orm-sync/src/query/delete.rs","lineNumber":212,"sourceCode":"    ///\n    /// # Panics\n    ///\n    /// Should not panic.\n    pub fn filter_by_ids<I>(mut self, values: I) -> Self\n    where\n        I: IntoIterator<Item = <E::PrimaryKey as PrimaryKeyTrait>::ValueType>,\n    {\n        self.query.cond_where(\n            column_tuple_in_condition(\n                &E::default().table_ref(),\n                &E::primary_key_identity(),\n                &values\n                    .into_iter()\n                    .map(|v| v.into_value_tuple())\n                    .collect::<Vec<_>>(),\n                DbBackend::Sqlite,\n            )\n            .expect(\"trait bound ensured arity\"),\n        );\n        self\n    }\n\n    #[doc(hidden)]\n    /// # Panics\n    ///\n    /// Panic if `ValueTuple` arity does not match primary key\n    pub fn filter_by_value_tuples(mut self, values: &[ValueTuple], db_backend: DbBackend) -> Self {\n        self.query.cond_where(\n            column_tuple_in_condition(\n                &E::default().table_ref(),\n                &E::primary_key_identity(),\n                values,\n                db_backend,\n            )\n            .expect(\"\"),\n        );","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/SeaQL/sea-orm/blob/e29bcd1b417c41a553b386fe94511d7c64a1c8ec/sea-orm-sync/src/query/delete.rs#L194-L230","documentation":"`DeleteMany::filter_by_ids` builds a tuple-IN condition on the primary key and validates it via `column_tuple_in_condition(...).expect(\"trait bound ensured arity\")`. The expectation is that the generic `IntoValueTuple` trait bounds guarantee every value's tuple length matches the primary key arity. A panic means values whose tuple arity mismatches the entity's composite primary key slipped through.","triggerScenarios":"Calling `delete_by_ids` / `filter_by_ids` with values whose `into_value_tuple()` produces a different number of elements than the entity's primary key arity — e.g. single values for a 2-column composite key or vice versa.","commonSituations":"Refactoring a table from single to composite primary key while old call sites still pass plain ids; mixing id types from different entities; deserializing ids from JSON into the wrong shape.","solutions":["Pass primary key values with the exact arity: single value for one-column keys, `(a, b)` tuples for composite keys.","Type the ids as `(<Entity as EntityTrait>::PrimaryKey)`-compatible tuples and let the compiler check.","Add a compile-time test calling filter_by_ids for each entity to catch arity drift."],"exampleFix":"// before\npost_tag::Entity::delete_by_id(vec![tag_id]) // composite key needs pairs\n// after\npost_tag::Entity::delete_by_id(vec![(post_id, tag_id)])","handlingStrategy":"type-guard","validationCode":"// ensure ids arity matches the entity's primary key\nlet arity = <PostTag::PrimaryKey as PrimaryKeyTrait>::ValueType::arity(); // e.g. 2\nlet ok = ids.iter().all(|v| value_tuple_len(v) == arity);","typeGuard":"fn as_pk<E: EntityTrait>(v: E::PrimaryKey) -> E::PrimaryKey { v } // only correctly-arity keys typecheck","tryCatchPattern":null,"preventionTips":["Type id collections as the entity's PrimaryKey values, not raw scalars.","Update call sites whenever a table's primary key changes arity.","Add compile-time tests calling filter_by_ids for each entity."],"tags":["panic","delete","tuple","arity"],"backgroundTag":"invalid-argument-value","analyzedSha":"e29bcd1b417c41a553b386fe94511d7c64a1c8ec","analyzedAt":"2026-09-10T11:31:52.468Z","contentChangedAt":"2026-09-10T11:31:52.468Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}