Error Handling
BigDecimal.js throws plain built-in errors — there is no custom error class to import. The rule is simple:
Everywhere Java's
BigDecimalthrowsArithmeticExceptionorNumberFormatException, BigDecimal.js throws aRangeError.
So one catch pattern covers every arithmetic failure:
The message text closely follows the JDK's, so if you are porting Java code the conditions below will look familiar.
When errors are thrown
Parsing and construction
Big(...) (and BigDecimal.fromValue) throws a RangeError for:
- strings that are not valid decimal numbers: multiple decimal points or signs, no digits, a missing or malformed exponent after
e/E - an exponent whose resulting scale would fall outside the 32-bit integer range. Note it is the scale that must fit, not the exponent:
Big('1E+2147483648')is accepted (its scale is-2147483648, which fits) whileBig('1E-2147483648')throws, because that scale would be+2147483648. This mirrors the JDK, which changed in Java 19 so thatBig(x.toString())always round-trips - a
numberoutside[-Number.MAX_VALUE, Number.MAX_VALUE](NaN,Infinity) - invalid argument combinations: passing both
scaleand aMathContext, or passingscalewith a non-integernumber
MC(...) (and the MathContext constructor) throws a RangeError for a negative precision or an invalid rounding mode.
Division
dividethrows when the exact quotient has an infinite decimal expansion —Non-terminating decimal expansion; no exact representable decimal result.Pass aMathContext(divideWithMathContext) or a scale + rounding mode to get a rounded result instead.- Any division by zero throws
Division by zero;0 ÷ 0throwsDivision undefined. divideToIntegralValue/divideAndRemainderwith aMathContextthrowDivision impossiblewhen the integer part needs more digits than the requested precision.
RoundingMode.UNNECESSARY
UNNECESSARY asserts that no rounding will happen. If the operation would need to round, it throws Rounding necessary — Java's behavior exactly:
Exact conversions
The *Exact methods throw instead of silently losing information — a nonzero fractional part or an out-of-range value is a RangeError:
numberValueExact()— value cannot be represented exactly as a JSnumberintValueExact(),shortValueExact(),byteValueExact(),longValueExact()— fractional part, or outside the Java type's range (Overflow)toBigIntExact()/toBigIntegerExact()— nonzero fractional part
Scale and precision limits
- Results whose scale would leave the 32-bit integer range throw
Scale too high/Scale too less(Java: "Underflow" / "Overflow"). pow(n)requires|n| ≤ 999999999, and negative exponents require a positiveMathContextprecision — otherwiseInvalid operation.sqrtof a negative value throwsAttempted square root of negative BigDecimal; withUNNECESSARY, an inexact square root throws.toFixed/toExponential/toPrecisionvalidate their arguments (non-negative / positive integers) with aRangeError, matching how JSNumbermethods reject bad arguments.
Malformed precision and scale
Java types both precision and scale as int, so a fractional or non-finite value is impossible there. JavaScript has only number, so both are validated on the way in:
MC(p)requirespto be an integer in[0, 2147483647]—MC(1.5),MC(NaN)andMC(Infinity)throwMathContext precision must be an integer, and values above theintrange throwout of the 32-bit integer range.Big(value, scale)requiresscaleto be an integer in the 32-bit range —Big(1n, NaN)andBig(1n, 1.5)throwScale must be an integer.- The operations that take a scale, exponent or point shift —
divide(d, scale, rm),setScale,scaleByPowerOfTen,movePointLeft,movePointRight— require the same. These areintparameters in Java, so an out-of-range value cannot be passed there at all; passing one here throwsout of the 32-bit integer rangerather than producing a value Java could not represent. This is distinct from an in-range argument whose resulting scale overflows, which still reportsScale too high/Scale too less(see below).
These are rejected at construction rather than at use because a fractional precision would otherwise reach the digit-stepping reduction loops in round() and sqrt(), which can never converge on a non-integer target, and a NaN scale would reach the string layout and produce malformed output such as '1ENaN'.
Why RangeError?
Java signals arithmetic failure with ArithmeticException; JavaScript has no such class, and RangeError ("a value is not in the set or range of allowed values") is the closest built-in match — it's what Number.prototype.toFixed throws for a bad argument. Using a built-in keeps the zero-dependency promise and works with instanceof across module copies.
Version note
Before 1.7.0 there was a single exception: MathContext threw TypeError for an invalid rounding mode. Since 1.7.0 it throws RangeError like every other validation failure.