TheAlgorithms/Python · error · Exception
Principal borrowed must be > 0
Error message
Principal borrowed must be > 0
What it means
Raised by equated_monthly_installments() in financial/equated_monthly_installments.py when principal <= 0. The EMI formula multiplies principal into the annuity factor, so a non-positive loan amount is meaningless; this is the first of three sequential input checks (principal, then rate, then years). Note the function raises bare Exception, not ValueError — so a `except ValueError` handler will not catch it.
Source
Thrown at financial/equated_monthly_installments.py:38
>>> equated_monthly_installments(25000, 0.12, 3)
830.3577453212793
>>> equated_monthly_installments(25000, 0.12, 10)
358.67737100646826
>>> equated_monthly_installments(0, 0.12, 3)
Traceback (most recent call last):
...
Exception: Principal borrowed must be > 0
>>> equated_monthly_installments(25000, -1, 3)
Traceback (most recent call last):
...
Exception: Rate of interest must be >= 0
>>> equated_monthly_installments(25000, 0.12, 0)
Traceback (most recent call last):
...
Exception: Years to repay must be an integer > 0
"""
if principal <= 0:
raise Exception("Principal borrowed must be > 0")
if rate_per_annum < 0:
raise Exception("Rate of interest must be >= 0")
if years_to_repay <= 0 or not isinstance(years_to_repay, int):
raise Exception("Years to repay must be an integer > 0")
# Yearly rate is divided by 12 to get monthly rate
rate_per_month = rate_per_annum / 12
# Years to repay is multiplied by 12 to get number of payments as payment is monthly
number_of_payments = years_to_repay * 12
return (
principal
* rate_per_month
* (1 + rate_per_month) ** number_of_payments
/ ((1 + rate_per_month) ** number_of_payments - 1)
)
View on GitHub (pinned to f5988cc097)
Solutions
- Pass a strictly positive principal in the loan's currency units.
- Validate at the input boundary (form/parser): require principal > 0 before calling.
- When catching, use `except Exception` (or a broad catch) because this library raises bare Exception, unlike its ValueError-based siblings.
Example fix
# before
emi = equated_monthly_installments(0, 0.12, 3) # Exception
# after
if principal > 0:
emi = equated_monthly_installments(principal, 0.12, 3) Defensive patterns
Strategy: validation
Validate before calling
if principal <= 0:
raise LoanInputError("principal must be > 0") Type guard
def valid_principal(p) -> bool:
return isinstance(p, (int, float)) and p > 0 Try / catch
# NOTE: this function raises bare Exception, not ValueError
try:
emi = equated_monthly_installments(principal, rate, years)
except Exception as exc: # intentional: matches the library's bare raise
raise LoanInputError(str(exc)) from exc Prevention
- Require principal > 0 in form validation before calling.
- Remember this module raises Exception (not ValueError) — write your handler accordingly.
- Reject zero-defaulted optional loan fields at deserialization.
When it happens
Trigger: equated_monthly_installments(-25000, 0.12, 3) or principal=0; amounts parsed from user input where an empty string became 0; loans denominated in subunits (paise/cents) accidentally divided down to 0.
Common situations: Form fields defaulting to 0; currency conversions that floor small values to 0; test fixtures using 0 as a 'no loan' sentinel.
Related errors
- Rate of interest must be >= 0
- Years to repay must be an integer > 0
- window_size must be > 0
- days_between_payments must be > 0
- daily_interest_rate must be >= 0
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/35a03278a24e4bf2.
Report an issue: GitHub.