{"record":{"id":"e63606b5b44e5456","repo":"diesel-rs/diesel","slug":"maximal-supported-day-interval-size-is-32-bit","errorCode":null,"errorMessage":"Maximal supported day interval size is 32 bit","messagePattern":"Maximal supported day interval size is 32 bit","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"diesel/src/pg/expression/extensions/interval_dsl.rs","lineNumber":223,"sourceCode":"    }\n\n    fn minutes(self) -> PgInterval {\n        i64::from(self).minutes()\n    }\n\n    fn hours(self) -> PgInterval {\n        i64::from(self).hours()\n    }\n}\n\nimpl IntervalDsl for i64 {\n    fn microseconds(self) -> PgInterval {\n        PgInterval::from_microseconds(self)\n    }\n\n    fn days(self) -> PgInterval {\n        i32::try_from(self)\n            .expect(\"Maximal supported day interval size is 32 bit\")\n            .days()\n    }\n\n    fn months(self) -> PgInterval {\n        i32::try_from(self)\n            .expect(\"Maximal supported month interval size is 32 bit\")\n            .months()\n    }\n}\n\n#[allow(clippy::cast_possible_truncation)] // we want to truncate\nimpl IntervalDsl for f64 {\n    fn microseconds(self) -> PgInterval {\n        (self.round() as i64).microseconds()\n    }\n\n    fn days(self) -> PgInterval {\n        let fractional_days = (self.fract() * 86_400.0).seconds();","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/diesel-rs/diesel/blob/6fa6ed01b24b24248ab2a611698d0a7c6a2e9120/diesel/src/pg/expression/extensions/interval_dsl.rs#L205-L241","documentation":"Diesel's PgInterval stores the `days` field as i32. The `days()` method on interval builder integers converts the caller's integer (commonly i64) via `i32::try_from(self)` and panics with this message if the value does not fit in 32 bits. This is a runtime panic (an .expect), not a recoverable error.","triggerScenarios":"Calling e.g. `(1i64 << 40).days()` or any value > i32::MAX (2,147,483,647) / < i32::MIN on the interval DSL's days() builder.","commonSituations":"Computing a day count dynamically (multiplying years by 365 in i64) and passing it to days(); overflow after unit changes from weeks/months to days; user-supplied large durations.","solutions":["Validate the day count fits in i32 before calling .days() (value.abs() <= i32::MAX as i64).","Break large intervals into months/years: use .months() or .years() for big spans (also i32-bounded but larger effective range).","Clamp the interval to the maximum representable days before building the PgInterval.","Catch at a higher level: run interval construction behind a checked conversion so invalid input is rejected by app validation, not a panic."],"exampleFix":"// before\nlet interval = duration_days_i64.days(); // panics if > i32::MAX\n// after\nlet days = i32::try_from(duration_days_i64)\n    .map_err(|_| anyhow::anyhow!(\"interval too large\"))?;\nlet interval = days.days();","handlingStrategy":"validation","validationCode":"fn fits_i32(v: i64) -> bool { v >= i32::MIN as i64 && v <= i32::MAX as i64 }\n// guard: if fits_i32(days) { days.days() } else { split into months/years }","typeGuard":"fn as_day_count(v: i64) -> Option<i32> { i32::try_from(v).ok() }","tryCatchPattern":"// .expect() panics; you cannot catch it. Validate instead:\nlet days = i32::try_from(raw_days).map_err(|_| Error::IntervalTooLarge)?;\nlet interval = days.days();","preventionTips":["Range-check day/month values against i32 bounds before building intervals.","Express large durations in months or years via the DSL.","Never feed unvalidated user input straight into .days()/.months()."],"tags":["diesel","postgres","interval","overflow","panic"],"backgroundTag":"value-out-of-range","analyzedSha":"6fa6ed01b24b24248ab2a611698d0a7c6a2e9120","analyzedAt":"2026-09-07T01:50:13.074Z","contentChangedAt":"2026-09-07T01:50:13.074Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}