diesel-rs/diesel · error
Failed to convert BigDecimal to PgNumeric
Error message
Failed to convert BigDecimal to PgNumeric
What it means
Runtime panic from the deprecated From<BigDecimal> for PgNumeric conversion (kept for backward compatibility; modern ToSql impls use a failable TryFrom-style path instead). Converting an arbitrary BigDecimal into PgNumeric can fail (e.g. digits that do not fit the base-10000 representation), and this legacy infallible API panics with this message in that case. Fix: migrate to the failable conversion path instead of the legacy From impl.
Solutions
- Reduce the scale or digit count of the BigDecimal
- Normalize the value before conversion
- Handle unsupported precision with a custom ToSql implementation
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at diesel/src/pg/types/numeric.rs:92 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07).
Data as JSON: /api/errors/bbbf7ec6c49280e5.
Report an issue: GitHub.
Appendix: source
Thrown at diesel/src/pg/types/numeric.rs:92
#[cfg(all(feature = "postgres_backend", feature = "numeric"))]
impl TryFrom<PgNumeric> for BigDecimal {
type Error = Box<dyn Error + Send + Sync>;
fn try_from(numeric: PgNumeric) -> deserialize::Result<Self> {
(&numeric).try_into()
}
}
// that should likely be a `TryFrom` impl
// TODO: diesel 3.0
// This now mostly exists for backward compatibility
// Our own `ToSql` impls don't call it anymore in favour of calling
// the failable inner function instead
#[cfg(all(feature = "postgres_backend", feature = "numeric"))]
impl<'a> From<&'a BigDecimal> for PgNumeric {
fn from(decimal: &'a BigDecimal) -> Self {
try_convert_decimal_to_pg_numeric(decimal)
.expect("Failed to convert BigDecimal to PgNumeric")
}
}
// NOTE(clippy): No `std::ops::MulAssign` impl for `BigInt`
// NOTE(clippy): Clippy suggests to replace the `.take_while(|i| i.is_zero())`
// with `.take_while(Zero::is_zero)`, but that's a false positive.
// The closure gets an `&&i16` due to autoderef `<i16 as Zero>::is_zero(&self) -> bool`
// is called. There is no impl for `&i16` that would work with this closure.
#[allow(clippy::assign_op_pattern, clippy::redundant_closure)]
#[cfg(all(feature = "postgres_backend", feature = "numeric"))]
fn try_convert_decimal_to_pg_numeric(
decimal: &BigDecimal,
) -> Result<PgNumeric, Box<dyn core::error::Error + Send + Sync>> {
let (mut integer, scale) = decimal.as_bigint_and_exponent();
// Handling of negative scale
let scale = if scale < -131064 {
// that's a guard avoiding the potential expensive calculation belowView on GitHub (pinned to 6fa6ed01b2)