Skip to content

fix(common_utils): return an error instead of panicking when a major-unit amount overflows Decimal - #14070

Open
edubraqd wants to merge 1 commit into
juspay:mainfrom
edubraqd:fix/major-unit-conversion-overflow
Open

edubraqd wants to merge 1 commit into
juspay:mainfrom
edubraqd:fix/major-unit-conversion-overflow

Conversation

@edubraqd

@edubraqd edubraqd commented Sep 4, 2026 •

Copy link
Copy Markdown

Type of Change

  • Bugfix

Description

FloatMajorUnit::to_minor_unit_as_i64 and StringMajorUnit::to_minor_unit_as_i64 scale the
parsed amount with amount_decimal * Decimal::from(100) (or 1000 for three-decimal
currencies). rust_decimal's Mul implementation panics on overflow
(Multiplication overflowed), so any amount in the range Decimal::MAX / 1000 .. Decimal::MAX
(roughly 7.9e25 .. 7.9e28) — which Decimal::from_f64 / Decimal::from_str happily accept —
takes the handler down instead of surfacing as a conversion error. The i64 overflow right
after it is already handled through ParsingError::DecimalToI64ConversionFailure, so the two
overflow paths were inconsistent.

These conversions run through AmountConvertor::convert_back on connector responses
(convert_back_amount_to_minor_units in hyperswitch_connectors, used for the
authorize / sync / capture integrity objects), so a malformed or absurd amount coming back from a
connector should produce ConnectorError::AmountConversionFailed, not a panic.

This PR moves the scaling into a small scale_major_to_minor helper that uses checked_mul and
maps the overflow to the existing DecimalToI64ConversionFailure (the result would not fit in an
i64 either), and adds a unit test for both the Decimal overflow and the i64 overflow.

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

Found while running a small property-style harness over the pure helpers in common_utils
with extreme inputs. Reproduction on main:

use common_utils::types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector};
let amount: FloatMajorUnit = serde_json::from_str("1e27").unwrap();
let _ = FloatMajorUnitForConnector.convert_back(amount, common_enums::Currency::USD);
// thread panicked at 'Multiplication overflowed', rust_decimal/src/arithmetic_impls.rs

The same happens for StringMajorUnit with "792281625142643375935439503.36".

How did you test it?

  • cargo test -p common_utils --lib types::amount_conversion_tests — the new
    amount_conversion_back_from_major_unit_overflow_is_an_error panics on main and passes with
    this change; the existing round-trip tests are unchanged.
  • cargo +nightly fmt --all and cargo clippy -p common_utils --lib --tests are clean.

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

Closes #14199

@edubraqd
edubraqd requested a review from a team as a code owner September 4, 2026 22:42
@semanticdiff-com

semanticdiff-com Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  crates/common_utils/src/types.rs  20% smaller

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] FloatMajorUnit / StringMajorUnit to_minor_unit_as_i64 panic on Decimal overflow instead of returning a conversion error

1 participant