TheAlgorithms/Python · error · ValueError
principal must be > 0
Error message
principal must be > 0
What it means
Raised by simple_interest() in financial/interest.py when principal <= 0. It is the third and final check, so both days and rate are already valid when it fires. The message text is shared verbatim with the principal checks in compound_interest and apr_interest in the same module.
Source
Thrown at financial/interest.py:38
>>> simple_interest(10000.0, -0.06, 3)
Traceback (most recent call last):
...
ValueError: daily_interest_rate must be >= 0
>>> simple_interest(-10000.0, 0.06, 3)
Traceback (most recent call last):
...
ValueError: principal must be > 0
>>> simple_interest(5500.0, 0.01, -5)
Traceback (most recent call last):
...
ValueError: days_between_payments must be > 0
"""
if days_between_payments <= 0:
raise ValueError("days_between_payments must be > 0")
if daily_interest_rate < 0:
raise ValueError("daily_interest_rate must be >= 0")
if principal <= 0:
raise ValueError("principal must be > 0")
return principal * daily_interest_rate * days_between_payments
def compound_interest(
principal: float,
nominal_annual_interest_rate_percentage: float,
number_of_compounding_periods: float,
) -> float:
"""
>>> compound_interest(10000.0, 0.05, 3)
1576.2500000000014
>>> compound_interest(10000.0, 0.05, 1)
500.00000000000045
>>> compound_interest(0.5, 0.05, 3)
0.07881250000000006
>>> compound_interest(10000.0, 0.06, -4)
Traceback (most recent call last):
...View on GitHub (pinned to f5988cc097)
Solutions
- Pass a strictly positive principal amount.
- If your ledger stores debts negative, negate at the boundary: `simple_interest(-balance, ...)` when balance < 0.
- Validate the full triple (days > 0, rate >= 0, principal > 0) before calling to fail with one clear message.
Example fix
# before si = simple_interest(-10000.0, 0.06, 3) # ValueError # after si = simple_interest(10000.0, 0.06, 3)
Defensive patterns
Strategy: validation
Validate before calling
if principal <= 0:
raise InputError("principal must be > 0") Type guard
def valid_principal(p) -> bool:
return isinstance(p, (int, float)) and p > 0 Try / catch
try:
si = simple_interest(principal, daily_rate, days)
except ValueError as exc:
raise InputError(str(exc)) from exc Prevention
- Normalize negative-balance ledger conventions at the system edge.
- Reject zero-defaulted principal fields during payload validation.
- The message is shared across interest.py functions — check the traceback frame to see which call raised.
When it happens
Trigger: simple_interest(-10000.0, 0.06, 3) or principal=0.0; ledger rows where a debit was stored as a negative amount; empty form input coerced to 0.
Common situations: Accounting systems storing liabilities as negative numbers; missing values defaulting to 0 in spreadsheets/CSV; test fixtures with a 0 principal sentinel.
Related errors
- days_between_payments must be > 0
- daily_interest_rate must be >= 0
- number_of_compounding_periods must be > 0
- nominal_annual_interest_rate_percentage must be >= 0
- Principal borrowed must be > 0
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/f6179887445c733a.
Report an issue: GitHub.